diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 883daf8e40..ee554e117e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -37,17 +37,17 @@ jobs: - uses: actions/checkout@v6 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: ${{ env.IMAGE }} @@ -60,7 +60,7 @@ jobs: - name: Build and push Docker images id: build - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: cache-from: type=gha cache-to: type=gha,mode=min @@ -77,7 +77,7 @@ jobs: touch "${{ runner.temp }}/digests/${digest#sha256:}" - name: Upload digest - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: digests-${{ env.PLATFORM_PAIR }} path: ${{ runner.temp }}/digests/* @@ -93,23 +93,23 @@ jobs: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY@L}" >> $GITHUB_ENV echo "CURRENT_DATE_NST=$(date +'%Y%m%d-%H%M%S' -d '-3 hours -30 minutes')" >> $GITHUB_ENV - name: Download digests - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: path: ${{ runner.temp }}/digests pattern: digests-* merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: ${{ env.IMAGE }} tags: | diff --git a/.tx/config b/.tx/config index 293681c974..ff0e36f735 100644 --- a/.tx/config +++ b/.tx/config @@ -276,6 +276,61 @@ trans.vi = public/language/vi/admin/advanced/events.json trans.zh_CN = public/language/zh-CN/admin/advanced/events.json trans.zh_TW = public/language/zh-TW/admin/advanced/events.json +[o:nodebb:p:nodebb:r:admin-advanced-jobs] +file_filter = public/language//admin/advanced/jobs.json +source_file = public/language/en-GB/admin/advanced/jobs.json +source_lang = en_GB +type = KEYVALUEJSON +trans.ar = public/language/ar/admin/advanced/jobs.json +trans.az = public/language/az/admin/advanced/jobs.json +trans.bg = public/language/bg/admin/advanced/jobs.json +trans.bn = public/language/bn/admin/advanced/jobs.json +trans.cs = public/language/cs/admin/advanced/jobs.json +trans.da = public/language/da/admin/advanced/jobs.json +trans.de = public/language/de/admin/advanced/jobs.json +trans.el = public/language/el/admin/advanced/jobs.json +trans.en_US = public/language/en-US/admin/advanced/jobs.json +trans.en@pirate = public/language/en-x-pirate/admin/advanced/jobs.json +trans.es = public/language/es/admin/advanced/jobs.json +trans.et = public/language/et/admin/advanced/jobs.json +trans.fa_IR = public/language/fa-IR/admin/advanced/jobs.json +trans.fi = public/language/fi/admin/advanced/jobs.json +trans.fr = public/language/fr/admin/advanced/jobs.json +trans.gl = public/language/gl/admin/advanced/jobs.json +trans.he = public/language/he/admin/advanced/jobs.json +trans.hr = public/language/hr/admin/advanced/jobs.json +trans.hu = public/language/hu/admin/advanced/jobs.json +trans.hy = public/language/hy/admin/advanced/jobs.json +trans.id = public/language/id/admin/advanced/jobs.json +trans.it = public/language/it/admin/advanced/jobs.json +trans.ja = public/language/ja/admin/advanced/jobs.json +trans.ko = public/language/ko/admin/advanced/jobs.json +trans.lt = public/language/lt/admin/advanced/jobs.json +trans.lv = public/language/lv/admin/advanced/jobs.json +trans.ms = public/language/ms/admin/advanced/jobs.json +trans.nb = public/language/nb/admin/advanced/jobs.json +trans.nl = public/language/nl/admin/advanced/jobs.json +trans.nn_NO = public/language/nn-NO/admin/advanced/jobs.json +trans.pl = public/language/pl/admin/advanced/jobs.json +trans.pt_BR = public/language/pt-BR/admin/advanced/jobs.json +trans.pt_PT = public/language/pt-PT/admin/advanced/jobs.json +trans.ro = public/language/ro/admin/advanced/jobs.json +trans.ru = public/language/ru/admin/advanced/jobs.json +trans.rw = public/language/rw/admin/advanced/jobs.json +trans.sc = public/language/sc/admin/advanced/jobs.json +trans.sk = public/language/sk/admin/advanced/jobs.json +trans.sl = public/language/sl/admin/advanced/jobs.json +trans.sq_AL = public/language/sq-AL/admin/advanced/jobs.json +trans.sr = public/language/sr/admin/advanced/jobs.json +trans.sv = public/language/sv/admin/advanced/jobs.json +trans.th = public/language/th/admin/advanced/jobs.json +trans.tr = public/language/tr/admin/advanced/jobs.json +trans.uk = public/language/uk/admin/advanced/jobs.json +trans.ur = public/language/ur/admin/advanced/jobs.json +trans.vi = public/language/vi/admin/advanced/jobs.json +trans.zh_CN = public/language/zh-CN/admin/advanced/jobs.json +trans.zh_TW = public/language/zh-TW/admin/advanced/jobs.json + [o:nodebb:p:nodebb:r:admin-advanced-logs] file_filter = public/language//admin/advanced/logs.json source_file = public/language/en-GB/admin/advanced/logs.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 82079a9636..6e6f7ec88f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,105 @@ +#### v4.9.2 (2026-03-11) + +##### Chores + +* up deps (c1e1e4fd) +* up deps (bbdf8263) +* up harmony (c179a959) +* up themes (4173793b) +* up themes (a8bb0034) +* up themes (829d8230) +* up themes (4f8bb728) +* up themes (58336941) +* up widgets (95fcb392) +* up peace (9b22d144) +* incrementing version number - v4.9.1 (72e44c86) +* update changelog for v4.9.1 (dcc46707) +* incrementing version number - v4.9.0 (3fdd1bef) +* incrementing version number - v4.8.1 (713ae0c0) +* incrementing version number - v4.8.0 (3fac737a) +* incrementing version number - v4.7.2 (cd419d8a) +* incrementing version number - v4.7.1 (afb88805) +* incrementing version number - v4.7.0 (e82d40f8) +* incrementing version number - v4.6.3 (9fc5b0f3) +* incrementing version number - v4.6.2 (f98747db) +* incrementing version number - v4.6.1 (f47aa678) +* incrementing version number - v4.6.0 (ee395bc5) +* incrementing version number - v4.5.2 (ad2da639) +* incrementing version number - v4.5.1 (69f4b61f) +* incrementing version number - v4.5.0 (f05c5d06) +* incrementing version number - v4.4.6 (074043ad) +* incrementing version number - v4.4.5 (6f106923) +* incrementing version number - v4.4.4 (d323af44) +* incrementing version number - v4.4.3 (d354c2eb) +* incrementing version number - v4.4.2 (55c510ae) +* incrementing version number - v4.4.1 (5ae79b4e) +* incrementing version number - v4.4.0 (0a75eee3) +* incrementing version number - v4.3.2 (b92b5d80) +* incrementing version number - v4.3.1 (308e6b9f) +* incrementing version number - v4.3.0 (bff291db) +* incrementing version number - v4.2.2 (17fecc24) +* incrementing version number - v4.2.1 (852a270c) +* incrementing version number - v4.2.0 (87581958) +* incrementing version number - v4.1.1 (b2afbb16) +* incrementing version number - v4.1.0 (36c80850) +* incrementing version number - v4.0.6 (4a52fb2e) +* incrementing version number - v4.0.5 (1792a62b) +* incrementing version number - v4.0.4 (b1125cce) +* incrementing version number - v4.0.3 (2b65c735) +* incrementing version number - v4.0.2 (73fe5fcf) +* incrementing version number - v4.0.1 (a461b758) +* incrementing version number - v4.0.0 (c1eaee45) + +##### New Features + +* add partial query help in acp manage users (330106e8) +* add mastodon share, closes #14069 (02b06492) +* clicking on timeago permalink of a nested reply (4bb281ae) + +##### Bug Fixes + +* mask-image to use line-heights instead of hardcoded 60% (2e21d214) +* closes #14074, only return url & name (92fcdd09) +* closes #14073, fix teasers from child categories (a391d01d) +* promises in groups.leave (8ec1cccc) +* hide unread anchor properly when close to bottom (457f6cf3) +* if quoting self, dont add @, but keep the username (304f89c0) +* unread count changes from 99+ to 123 (b9b63bf5) +* fix bottom sheet max-height so it doesn't push the top out of viewport (009be468) +* #14062 recipients is normal set (0be40810) +* add missing db call (d35c7455) +* closes #14062 (1fc3edf7) +* ghostscrollbar colors on dark skins (d6f5420b) +* #13239, unescape custom user field values (2f5fccdb) +* text-break on outgoing link (4f07b345) +* logic in checkRequired (2428602f) +* closes #14041, show specific error message (b2681646) +* dont crash if payload isnt Error (c98ef396) +* closes #14039, only keep chat input in view on the chats page (44434b0d) +* thumbs, send type for resize (30893a1a) +* #14033, fix gif profile images (06bf2abf) +* **deps:** + * update dependency multer to v2.1.1 (#14050) (8f960ff4) + * update dependency nodebb-plugin-emoji to v6.0.6 (#14034) (811344b8) + +##### Performance Improvements + +* make a single round trip for set(s)Remove (f6f51f83) +* cache groups:createtime (c4e9e1cb) + +##### Refactors + +* get rid of pop (4af03139) +* switch to cursor (4aea3a80) +* update upgrade script to scan for missing tid::recipients (75f52cad) +* move resolve flags and activitypub.out.remove.context (88b91c20) +* use includes (0c43e2da) + +##### Tests + +* fix spec (bdb91e82) +* fix btn tests (c8308718) + #### v4.9.1 (2026-03-01) ##### Chores diff --git a/docker-compose-pgsql.yml b/docker-compose-pgsql.yml index 24f9e0d10e..368a9c8054 100644 --- a/docker-compose-pgsql.yml +++ b/docker-compose-pgsql.yml @@ -14,7 +14,7 @@ services: - ./install/docker/setup.json:/usr/src/app/setup.json postgres: - image: postgres:18.2-alpine + image: postgres:18.3-alpine restart: unless-stopped environment: POSTGRES_USER: nodebb diff --git a/docker-compose.yml b/docker-compose.yml index ab7439bbcf..b639a559bd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,7 @@ services: - redis postgres: - image: postgres:18.2-alpine + image: postgres:18.3-alpine restart: unless-stopped environment: POSTGRES_USER: nodebb diff --git a/install/data/defaults.json b/install/data/defaults.json index fcbac89921..a6b25a2732 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -59,7 +59,7 @@ "resizeImageQuality": 80, "convertPastedImageTo": "image/jpeg", "topicThumbSize": 512, - "minimumTitleLength": 3, + "minimumTitleLength": 0, "maximumTitleLength": 255, "minimumUsernameLength": 2, "maximumUsernameLength": 16, @@ -208,5 +208,6 @@ "activitypubUserPruneDays": 7, "activitypubFilter": 0, "activitypubSummaryLimit": 500, - "activitypubBreakString": "[...]" + "activitypubBreakString": "[...]", + "activitypubWorldDefaultCid": -1 } diff --git a/install/package.json b/install/package.json index 45bc814366..c31cbf4889 100644 --- a/install/package.json +++ b/install/package.json @@ -42,7 +42,7 @@ "ace-builds": "1.43.6", "archiver": "7.0.1", "async": "3.2.6", - "autoprefixer": "10.4.24", + "autoprefixer": "10.4.27", "bcryptjs": "3.0.3", "benchpressjs": "2.5.5", "body-parser": "2.2.2", @@ -62,17 +62,18 @@ "connect-redis": "9.0.0", "cookie-parser": "1.4.7", "cron": "4.4.0", + "cronstrue": "3.14.0", "cropperjs": "1.6.2", "csrf-sync": "4.2.1", "daemon": "1.1.0", "diff": "8.0.3", - "esbuild": "0.27.3", + "esbuild": "0.27.4", "express": "4.22.1", "express-session": "1.19.0", "express-useragent": "2.1.0", "fetch-cookie": "3.2.0", "file-loader": "6.2.0", - "fs-extra": "11.3.3", + "fs-extra": "11.3.4", "graceful-fs": "4.2.11", "helmet": "7.2.0", "html-to-text": "9.0.5", @@ -88,7 +89,7 @@ "jsonwebtoken": "9.0.3", "lodash": "4.17.23", "logrotate-stream": "0.2.9", - "lru-cache": "11.2.6", + "lru-cache": "11.2.7", "mime": "3.0.0", "mkdirp": "3.0.1", "mongodb": "7.1.0", @@ -97,29 +98,29 @@ "multer": "2.1.1", "nconf": "0.13.0", "nodebb-plugin-2factor": "7.6.1", - "nodebb-plugin-composer-default": "10.3.26", + "nodebb-plugin-composer-default": "10.3.28", "nodebb-plugin-dbsearch": "6.4.1", "nodebb-plugin-emoji": "6.0.6", "nodebb-plugin-emoji-android": "4.1.1", "nodebb-plugin-link-preview": "2.2.3", "nodebb-plugin-markdown": "13.2.4", - "nodebb-plugin-mentions": "4.8.17", + "nodebb-plugin-mentions": "4.8.18", "nodebb-plugin-spam-be-gone": "2.3.2", - "nodebb-plugin-web-push": "0.7.6", + "nodebb-plugin-web-push": "0.7.7", "nodebb-rewards-essentials": "1.0.2", - "nodebb-theme-harmony": "2.2.51", + "nodebb-theme-harmony": "2.2.61", "nodebb-theme-lavender": "7.1.21", "nodebb-theme-peace": "2.2.57", - "nodebb-theme-persona": "14.2.27", + "nodebb-theme-persona": "14.2.33", "nodebb-widget-essentials": "7.0.43", - "nodemailer": "8.0.1", + "nodemailer": "8.0.3", "nprogress": "0.2.0", "passport": "0.7.0", "passport-http-bearer": "1.0.1", "passport-local": "1.0.0", - "pg": "8.18.0", - "pg-cursor": "2.17.0", - "postcss": "8.5.6", + "pg": "8.20.0", + "pg-cursor": "2.19.0", + "postcss": "8.5.8", "postcss-clean": "1.2.0", "pretty": "^2.0.0", "progress-webpack-plugin": "1.0.16", @@ -131,12 +132,12 @@ "rtlcss": "4.3.0", "sanitize-html": "2.17.1", "sass": "1.98.0", - "satori": "0.19.2", + "satori": "0.25.0", "sbd": "^1.0.19", "semver": "7.7.4", "serve-favicon": "2.5.1", "sharp": "0.34.5", - "sitemap": "9.0.0", + "sitemap": "9.0.1", "socket.io": "4.8.3", "socket.io-client": "4.8.3", "@socket.io/redis-adapter": "8.3.0", @@ -148,10 +149,10 @@ "timeago": "1.6.7", "tinycon": "0.6.8", "toobusy-js": "0.5.1", - "tough-cookie": "6.0.0", + "tough-cookie": "6.0.1", "undici": "^7.10.0", "validator": "13.15.26", - "webpack": "5.105.2", + "webpack": "5.105.4", "webpack-merge": "6.0.1", "winston": "3.19.0", "workerpool": "10.0.1", @@ -161,22 +162,22 @@ }, "devDependencies": { "@apidevtools/swagger-parser": "10.1.0", - "@commitlint/cli": "20.4.2", - "@commitlint/config-angular": "20.4.2", + "@commitlint/cli": "20.5.0", + "@commitlint/config-angular": "20.5.0", "coveralls": "3.1.1", "@eslint/js": "10.0.1", - "@stylistic/eslint-plugin": "5.9.0", + "@stylistic/eslint-plugin": "5.10.0", "eslint-config-nodebb": "2.0.1", - "globals": "17.3.0", + "globals": "17.4.0", "grunt": "1.6.1", "grunt-contrib-watch": "1.1.0", "husky": "8.0.3", - "jsdom": "28.1.0", - "lint-staged": "16.2.7", + "jsdom": "29.0.0", + "lint-staged": "16.4.0", "mocha": "11.7.5", "mocha-lcov-reporter": "1.3.0", "mockdate": "3.0.5", - "nyc": "17.1.0", + "nyc": "18.0.0", "smtp-server": "3.18.1" }, "optionalDependencies": { @@ -203,4 +204,4 @@ "url": "https://github.com/barisusakli" } ] -} \ No newline at end of file +} diff --git a/public/images/screenshot-default.png b/public/images/screenshot-default.png new file mode 100644 index 0000000000..cd231ecb2a Binary files /dev/null and b/public/images/screenshot-default.png differ diff --git a/public/language/ar/admin/advanced/jobs.json b/public/language/ar/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ar/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ar/admin/dashboard.json b/public/language/ar/admin/dashboard.json index 59aa11298f..963c5295af 100644 --- a/public/language/ar/admin/dashboard.json +++ b/public/language/ar/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "مواضيع", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "آخر 7 ايام", "page-views-thirty": "آخر 30 يوماً", "page-views-last-day": "آخر 24 ساعة", - "page-views-custom": "مدة زمنية مخصصة", + "page-views-custom": "Custom Range", "page-views-custom-start": "بداية المدة", "page-views-custom-end": "نهاية المده", "page-views-custom-help": "أدخل نطاقا زمنيا لمرات مشاهدة الصفحات التي ترغب في عرضها. إذا لم يظهر منتقي التاريخ، فإن التنسيق المقبول هو YYYY-MM-DD", diff --git a/public/language/ar/admin/manage/users.json b/public/language/ar/admin/manage/users.json index 992f39e148..e76b32cc66 100644 --- a/public/language/ar/admin/manage/users.json +++ b/public/language/ar/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/ar/admin/menu.json b/public/language/ar/admin/menu.json index 7e65c42a79..6ab217205b 100644 --- a/public/language/ar/admin/menu.json +++ b/public/language/ar/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/ar/admin/settings/activitypub.json b/public/language/ar/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/ar/admin/settings/activitypub.json +++ b/public/language/ar/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ar/admin/settings/general.json b/public/language/ar/admin/settings/general.json index 43e7f5a38c..ad5fba74ae 100644 --- a/public/language/ar/admin/settings/general.json +++ b/public/language/ar/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "الكلمات الدليله للموقع", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "صورة", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "رفع", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/ar/error.json b/public/language/ar/error.json index fb8666a0f4..2471bc4452 100644 --- a/public/language/ar/error.json +++ b/public/language/ar/error.json @@ -1,5 +1,6 @@ { "invalid-data": "بيانات غير صحيحة", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/ar/global.json b/public/language/ar/global.json index 1e131164ff..7ac7927d0c 100644 --- a/public/language/ar/global.json +++ b/public/language/ar/global.json @@ -24,10 +24,10 @@ "cancel": "Cancel", "close": "أغلق", "pagination": "الصفحات", - "pagination.previouspage": "Previous Page", - "pagination.nextpage": "Next Page", - "pagination.firstpage": "First Page", - "pagination.lastpage": "Last Page", + "pagination.previouspage": "الصفحة السابقة", + "pagination.nextpage": "الصفحة التالية", + "pagination.firstpage": "الصفحة الأولى", + "pagination.lastpage": "الصفحة الأخيرة", "pagination.out-of": "%1 من %2", "pagination.enter-index": "Go to post index", "pagination.go-to-page": "Go to page", diff --git a/public/language/ar/world.json b/public/language/ar/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/ar/world.json +++ b/public/language/ar/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/az/admin/advanced/jobs.json b/public/language/az/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/az/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/az/admin/dashboard.json b/public/language/az/admin/dashboard.json index c740102c9e..4baa8782dd 100644 --- a/public/language/az/admin/dashboard.json +++ b/public/language/az/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Mövzular", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Son 7 Gün", "page-views-thirty": "Son 30 Gün", "page-views-last-day": "Son 24 saat", - "page-views-custom": "Fərdi tarix aralığı", + "page-views-custom": "Custom Range", "page-views-custom-start": "Aralığın başlanğıcı", "page-views-custom-end": "Aralığın sonu", "page-views-custom-help": "Baxmaq istədiyiniz səhifə baxışlarının tarix diapazonunu daxil edin. Əgər tarix seçici mövcud deyilsə, qəbul edilən format YYYY-AA-GG-dir", diff --git a/public/language/az/admin/manage/users.json b/public/language/az/admin/manage/users.json index 5768ef94fb..fe0e3116b3 100644 --- a/public/language/az/admin/manage/users.json +++ b/public/language/az/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "Səhifə başına 250", "500-per-page": "Səhifə başına 500", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "İstifadəçi ID ilə", "search.uid-placeholder": "Axtarmaq üçün istifadəçi ID-sini daxil edin", "search.username": "İstifadəçi adı ilə", diff --git a/public/language/az/admin/menu.json b/public/language/az/admin/menu.json index 8e2cd059a8..c95561427b 100644 --- a/public/language/az/admin/menu.json +++ b/public/language/az/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Loqlar", "advanced/errors": "Xətalar", "advanced/cache": "Keş", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Məlumat", diff --git a/public/language/az/admin/settings/activitypub.json b/public/language/az/admin/settings/activitypub.json index c528187a81..d68d9dbdaf 100644 --- a/public/language/az/admin/settings/activitypub.json +++ b/public/language/az/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/az/admin/settings/general.json b/public/language/az/admin/settings/general.json index 6747b5b431..ec84fda492 100644 --- a/public/language/az/admin/settings/general.json +++ b/public/language/az/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Sayt təsviri", "keywords": "Saytın açar sözləri", "keywords-placeholder": "İcmanızı təsvir edən açar sözlər, vergüllə ayrılmış", - "logo-and-icons": "Saytın loqosu və ikonaları", + "logo-and-icons": "Media & Branding", "logo.image": "Şəkil", "logo.image-placeholder": "Forumun başlığında göstəriləcək loqoya gedən yol", "logo.upload": "Yüklə", @@ -35,6 +35,8 @@ "touch-icon.help": "Tövsiyə olunan ölçü və format: 512x512, yalnız PNG formatı. Əgər toxunma ikonu göstərilməyibsə, NodeBB favikondan istifadə etməyə qayıdacaq.", "maskable-icon": "Maskalana bilən (Ev ekranı) ikonu", "maskable-icon.help": "Tövsiyə olunan ölçü və format: 512x512, yalnız PNG formatı. Əgər maskalana bilən ikona göstərilməyibsə, NodeBB yenidən Touch Icon-a düşəcək.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Çıxış linklər", "outgoing-links.warning-page": "Gedən linklər xəbərdarlıq səhifəsindən istifadə edin", "search": "Axtarış", diff --git a/public/language/az/error.json b/public/language/az/error.json index 513bdcc314..a63ba99a7f 100644 --- a/public/language/az/error.json +++ b/public/language/az/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Etibarsız məlumat", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Yanlış JSON", "wrong-parameter-type": "`%1` mülkiyyəti üçün %3 növünün dəyəri gözlənilən idi, lakin bunun əvəzinə %2 alındı", "required-parameters-missing": "Bu API çağırışında tələb olunan parametrlər yoxdur: %1", diff --git a/public/language/az/world.json b/public/language/az/world.json index a61b75e11b..65e4bface8 100644 --- a/public/language/az/world.json +++ b/public/language/az/world.json @@ -1,6 +1,8 @@ { "name": "Dünya", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Eyni şəkildə, bu forumdan kənar istifadəçilər sizi izləməyə başlayarsa, o zaman yazılarınız həmin proqramlarda və vebsaytlarda da görünməyə başlayacaq.", "help.next-generation": "Bu, sosial medianın yeni nəslidir, bu gün töhfə verməyə başlayın!", - "onboard.title": "Sizin fediverse pəncərəniz...", - "onboard.what": "Bu, yalnız bu forumdan kənarda tapılan məzmundan ibarət sizin fərdiləşdirilmiş kateqoriyanızdır. Bu səhifədə nəyinsə görünüb-göstərilməməsi onları izlədiyinizdən və ya həmin postun izlədiyiniz biri tərəfindən paylaşılıb-paylaşılmamasından asılıdır.", - "onboard.why": "Bu forumdan kənarda gedən çox şey var və bunların heç də hamısı maraqlarınıza uyğun deyil. Buna görə də insanları izləmək, kimdənsə daha çox görmək istədiyinizi bildirməyin ən yaxşı yoludur.", - "onboard.how": "Bu arada, bu forumun daha nələr haqqında bildiyini görmək üçün yuxarıdakı qısayol düymələrinə klikləyə və bəzi yeni məzmunlar kəşf etməyə başlaya bilərsiniz!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/bg/admin/advanced/jobs.json b/public/language/bg/admin/advanced/jobs.json new file mode 100644 index 0000000000..dc0c0314a9 --- /dev/null +++ b/public/language/bg/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Задачи", + "job-name": "Име на задачата", + "schedule": "График", + "next-run": "Следващо изпълнение", + "last-duration": "Последна продължителност", + "running": "В процес на изпълнение", + "active": "Активни" +} \ No newline at end of file diff --git a/public/language/bg/admin/dashboard.json b/public/language/bg/admin/dashboard.json index d0cac8a896..cbf42291c7 100644 --- a/public/language/bg/admin/dashboard.json +++ b/public/language/bg/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "Нови потребители", "posts": "Публикации", "topics": "Теми", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "Отдалечени публикации", + "remote-topics": "Отдалечени теми", + "messages": "Съобщения", "page-views-seven": "Последните 7 дни", "page-views-thirty": "Последните 30 дни", "page-views-last-day": "Последните 24 часа", - "page-views-custom": "Интервал по избор", + "page-views-custom": "Персонализиран интервал", "page-views-custom-start": "Начална дата", "page-views-custom-end": "Крайна дата", "page-views-custom-help": "Въведете интервал от дати, за които искате да видите преглежданията на страниците. Ако не се появи календар за избор, можете да въведете датите във формат: ГГГГ-ММ-ДД", diff --git a/public/language/bg/admin/development/info.json b/public/language/bg/admin/development/info.json index 5ee980d748..87c5a3e104 100644 --- a/public/language/bg/admin/development/info.json +++ b/public/language/bg/admin/development/info.json @@ -8,7 +8,7 @@ "nodejs": "nodejs", "online": "на линия", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "използвана памет – rss/heap", "system-memory": "системна памет", "used-memory-process": "Използвана памет от процеса", "used-memory-os": "Използвана системна памет", diff --git a/public/language/bg/admin/manage/categories.json b/public/language/bg/admin/manage/categories.json index a18b30efb0..9e7365a595 100644 --- a/public/language/bg/admin/manage/categories.json +++ b/public/language/bg/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "Изберете категория", "set-parent-category": "Задайте базова категория", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "В тази секция можете да настроите правомощията за достъп до различните части на уеб сайта Правомощията могат да бъдат давани на отделни потребители или на цели групи.", "privileges.category-selector": "Настройване на правомощията за ", "privileges.warning": "Забележка: Настройките за правомощията влизат в сила моментално. Не е нужно да запазвате категорията след като промените тези настройки.", "privileges.section-viewing": "Правомощия за преглед", diff --git a/public/language/bg/admin/manage/custom-reasons.json b/public/language/bg/admin/manage/custom-reasons.json index 90a2e620af..a6fa61a983 100644 --- a/public/language/bg/admin/manage/custom-reasons.json +++ b/public/language/bg/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "title": "Управление на персонализираните причини", + "create-reason": "Създаване на причина", + "edit-reason": "Редактиране на причината", + "reasons-help": "Причините са предварително подготвени обяснения, които могат да се ползват при блокиране или заглушаване на потребители, както и при отхвърляне на публикации от опашката за одобрение.", + "reason-title": "Заглавие", + "reason-type": "Тип", + "reason-body": "Текст", + "reason-all": "Всички", + "reason-ban": "Блокиране", + "reason-mute": "Заглушаване", + "reason-post-queue": "Опашка за публикации", + "reason-type-help": "Видът на действието, за което може да се прилага тази причина. Ако изберете „всички“, то тя ще бъде налична за всички видове действия.", + "custom-reasons-saved": "Персонализираните причини са запазени успешно", + "delete-reason-confirm-x": "Наистина ли искате да изтриете персонализираната причина със заглавие %1?" } \ No newline at end of file diff --git a/public/language/bg/admin/manage/privileges.json b/public/language/bg/admin/manage/privileges.json index 6e8295b33f..279ee5f14c 100644 --- a/public/language/bg/admin/manage/privileges.json +++ b/public/language/bg/admin/manage/privileges.json @@ -8,7 +8,7 @@ "edit-privileges": "Редактиране на правомощията", "select-clear-all": "Избиране/изчистване на всичко", "chat": "Разговор", - "chat-with-privileged": "Разговор с някого с по-високи правомощия", + "chat-with-privileged": "Разговор с човек с по-високи правомощия", "upload-images": "Качване на изображения", "upload-files": "Качване на файлове", "signature": "Подпис", @@ -29,7 +29,7 @@ "access-topics": "Достъп до теми", "create-topics": "Създаване на теми", "reply-to-topics": "Отговаряне в теми", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "Допълнително публикуване на теми", "schedule-topics": "Насрочване на теми", "tag-topics": "Поставяне на етикети на теми", "edit-posts": "Редактиране на публикации", diff --git a/public/language/bg/admin/manage/users.json b/public/language/bg/admin/manage/users.json index 1b5dd3f7ac..b68fa15b10 100644 --- a/public/language/bg/admin/manage/users.json +++ b/public/language/bg/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 на страница", "500-per-page": "500 на страница", + "search.help": "Използвайте "*" за частични търсения. например: "*дума"", "search.uid": "По потребителски идентификатор", "search.uid-placeholder": "Въведете потребителски идентификатор, който да потърсите", "search.username": "По име на потребител", @@ -55,7 +56,7 @@ "inactive.12-months": "12 месеца", "users.uid": "потр. ид.", - "users.user-id": "User ID", + "users.user-id": "Потребителски ИД", "users.username": "потребителско име", "users.email": "е-поща", "users.no-email": "(няма е-поща)", @@ -64,7 +65,7 @@ "users.validation-pending": "Очаква потвърждение", "users.validation-expired": "Изтекла давност на потвърждението", "users.ip": "IP адрес", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "Скорошни IP адреси", "users.postcount": "брой публикации", "users.reputation": "репутация", "users.flags": "доклади", diff --git a/public/language/bg/admin/menu.json b/public/language/bg/admin/menu.json index af370099ca..5e66f9b801 100644 --- a/public/language/bg/admin/menu.json +++ b/public/language/bg/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "Настройки на %1", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "Федериране", + "federation/general": "Общи", + "federation/content": "Съдържание", + "federation/rules": "Категоризиране", + "federation/relays": "Препредаватели", + "federation/pruning": "Съхранение", + "federation/safety": "Доверие и защита", "section-appearance": "Външен вид", "appearance/themes": "Теми", @@ -78,6 +78,7 @@ "advanced/logs": "Журнали", "advanced/errors": "Грешки", "advanced/cache": "Кеш", + "advanced/jobs": "Задачи", "development/logger": "Журнал", "development/info": "Информация", diff --git a/public/language/bg/admin/settings/activitypub.json b/public/language/bg/admin/settings/activitypub.json index d9dfa05913..089529287a 100644 --- a/public/language/bg/admin/settings/activitypub.json +++ b/public/language/bg/admin/settings/activitypub.json @@ -46,9 +46,10 @@ "server.filter-help-hostname": "Въведете само имената на сървърите по-долу (например example.org), като всеки сървър трябва да е на отделен ред.", "server.filter-allow-list": "Това да се ползва като списък с разрешените сървъри", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "Изходящи", + "content.summary-limit": "Брой знаци, след които се създава обобщение", + "content.summary-limit-help": "Когато дадено съдържание е федерирано в посока извън този форум и превишава този брой знаци, ще се създаде обобщение, което се състои от всички завършени изречения до ограничението. (по подразбиране: 500)", + "content.break-string": "Разделител на съдържанието", + "content.break-string-help": "Този разделител може да бъде поставен ръчно от потребителите с по-високи правомощия, когато създават нови теми. Той казва на NodeBB да използва съдържанието до така посоченото място като част от обобщението. Ако този разделител не бъде използван, се прилага зададеният брой на знаците. (по подразбиране: [...])", + "content.world-default-cid": "Идентификатор на категория по подразбиране при съставяне на страница в „Света“" } \ No newline at end of file diff --git a/public/language/bg/admin/settings/email.json b/public/language/bg/admin/settings/email.json index 4f3ff7b24b..b61fa8b32c 100644 --- a/public/language/bg/admin/settings/email.json +++ b/public/language/bg/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "Групирането на връзките предотвратява създаването на нова връзка за всяко е-писмо. Тази настройка има ефект, само ако е включено „Транспорт чрез SMTP“.", "smtp-transport.allow-self-signed": "Разрешаване на самоподписаните сертификатите", "smtp-transport.allow-self-signed-help": "Включването на тази настройка ще позволи ползването на самоподписани и невалидни сертификати TLS.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "Е-писмото за изпробване на протокола SMTP беше изпратено успешно.", "template": "Редактирана не шаблона за е-писма", "template.select": "Изберете шаблон за е-писма", "template.revert": "Връщане на оригинала", - "test-smtp-settings": "Test SMTP Settings", - "testing": "Проба на е-писмата", - "testing.success": "Test Email Sent.", + "test-smtp-settings": "Настройки за изпробване на SMTP", + "testing": "Изпробване на е-писмата", + "testing.success": "Пробното е-писмо е изпратено.", "testing.select": "Изберете шаблон за е-писма", "testing.send": "Изпращане на пробно е-писмо", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "„%1“ ще се ползва за изпращане на пробни е-писма.", + "testing.send-help-smtp": "Транспортът по SMTP е включен и ще се използва за изпращане на е-писма.", + "testing.send-help-no-plugin": "Няма инсталирана добавка за изпращане на е-писма. По подразбиране ще се използва nodemailer.", + "testing.send-help": "Пробното е-писмо ще бъде изпратено до е-пощата на текущо вписания потребител, като се използват запазените настройки на тази страница.", "subscriptions": "Резюмета по е-поща", "subscriptions.disable": "Изключване на резюметата по е-пощата", "subscriptions.hour": "Време за разпращане", diff --git a/public/language/bg/admin/settings/general.json b/public/language/bg/admin/settings/general.json index 9c84b5413d..74b12dd3e2 100644 --- a/public/language/bg/admin/settings/general.json +++ b/public/language/bg/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Описание на уеб сайта", "keywords": "Ключови думи на уеб сайта", "keywords-placeholder": "Ключови думи, описващи общността Ви. Трябва да бъдат разделени със запетаи.", - "logo-and-icons": "Лого и иконки на уеб сайта", + "logo-and-icons": "Медийни материали", "logo.image": "Изображение", "logo.image-placeholder": "Път до логото, което да бъде показано в заглавната част на форума", "logo.upload": "Качване", @@ -35,6 +35,8 @@ "touch-icon.help": "Препоръчителен размер и формат: 512x512, само във формат „PNG“. Ако не е посочена иконка за сензорен екран, NodeBB ще използва иконката на уеб сайта.", "maskable-icon": "Маскируема иконка (за начален екран)", "maskable-icon.help": "Препоръчителен размер и формат: 512x512, само във формат „PNG“. Ако не е посочена маскируема иконка, NodeBB ще използва иконката за сензорен екран.", + "screenshot": "Екранна снимка", + "screenshot.help": "Препоръчителен размер и формат: между 320px и 3480px, само JPG и PNG. Ако няма зададена екранна снимка, NodeBB ще използва такава по подразбиране.", "outgoing-links": "Изходящи връзки", "outgoing-links.warning-page": "Показване на предупредителна страница при щракване върху външни връзки", "search": "Търсене", diff --git a/public/language/bg/admin/settings/notifications.json b/public/language/bg/admin/settings/notifications.json index 3dd327fd85..8587432df6 100644 --- a/public/language/bg/admin/settings/notifications.json +++ b/public/language/bg/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "Връзка за приветственото известие", "welcome-notification-uid": "Потр. ид. за приветственото известие", "post-queue-notification-uid": "Потр. ид. за опашката с публикации", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "Забавяне преди изпращането на е-писма с известия (секунди)", + "notification-delay-help": "Ако потребителят е прочел известието в рамките на това време, няма да се изпрати е-писмо.
По подразбиране: 60 секунди." } \ No newline at end of file diff --git a/public/language/bg/admin/settings/post.json b/public/language/bg/admin/settings/post.json index f39ea34f3c..d937bcddd2 100644 --- a/public/language/bg/admin/settings/post.json +++ b/public/language/bg/admin/settings/post.json @@ -29,7 +29,7 @@ "restrictions.stale-help": "Ако дадена тема е определена като „стара“, то потребителите, които се опитат да пишат в нея, ще получат предупредително съобщение. (0 = изключено)", "timestamp": "Време", "timestamp.cut-off": "Използване на дата след (в брой дни)", - "timestamp.cut-off-help": "Датите и времената ще бъдат показвани относително (напр. „преди 3 часа“ или „преди 5 дни“), и преведени на множество\n\\t\\t\\t\\t\\tезици. След определено време, този текст ще започне да показва самите дата и час, според езика на потребителя\n\\t\\t\\t\\t\\t(напр. „5 ноември 2016 15:30“).
(По подразбиране: 30, тоест един месец). Ако зададете 0, винаги ще се изписват дати, а ако оставите полето празно, времето ще бъде винаги относително.", + "timestamp.cut-off-help": "Датите и времената ще бъдат показвани относително (напр. „преди 3 часа“ или „преди 5 дни“), и преведени на множество\n\t\t\t\t\tезици. След определено време, този текст ще започне да показва самите дата и час, според езика на потребителя\n\t\t\t\t\t(напр. „5 ноември 2016 15:30“).
(По подразбиране: 30, тоест един месец). Ако зададете 0, винаги ще се изписват дати, а ако оставите полето празно, времето ще бъде винаги относително.", "timestamp.necro-threshold": "Мъртва граница (в дни)", "timestamp.necro-threshold-help": "Между публикациите ще бъде показано съобщение, ако времето между тях е по-дълго от мъртвата граница. (По подразбиране: 7, или една седмица). Задайте 0 за изключване.", "timestamp.topic-views-interval": "Интервал за увеличаване на броя на преглеждания на темите (в минути)", @@ -51,7 +51,7 @@ "signature.hide-duplicates": "Скриване на дублираните подписи в темите", "signature.max-length": "Максимална дължина на подписите", "composer": "Настройки за съставянето", - "composer-help": "Следващите настройки определят функционалностите и/или вида на елемента за съставяне на\n\\t\\t\\t\\tпубликация, който се използва от потребителите, когато те създават нови теми или отговорят в съществуващи.", + "composer-help": "Следващите настройки определят функционалностите и/или вида на елемента за съставяне на\n\t\t\t\tпубликация, който се използва от потребителите, когато те създават нови теми или отговорят в съществуващи.", "composer.show-help": "Показване на раздела „Помощ“", "composer.enable-plugin-help": "Позволяване на добавките да добавят съдържание в раздела за помощ", "composer.custom-help": "Персонализиран текст за помощ", diff --git a/public/language/bg/admin/settings/uploads.json b/public/language/bg/admin/settings/uploads.json index 1d3b584175..3f2b8cd13b 100644 --- a/public/language/bg/admin/settings/uploads.json +++ b/public/language/bg/admin/settings/uploads.json @@ -40,7 +40,7 @@ "default-avatar": "Персонализирано изображение по подразбиране", "upload": "Качване", "profile-image-dimension": "Размер на профилното изображение", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(в пиксели; по подразбиране: 200 пиксела)", "max-profile-image-size": "Максимален файлов размер на профилното изображение", "max-profile-image-size-help": "(в кибибайтове; по подразбиране: 256 КиБ)", "max-cover-image-size": "Максимален файлов размер на изображението на корицата", diff --git a/public/language/bg/admin/settings/web-crawler.json b/public/language/bg/admin/settings/web-crawler.json index 8286054a1f..7bc4bc0450 100644 --- a/public/language/bg/admin/settings/web-crawler.json +++ b/public/language/bg/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "Изключване на емисиите чрез RSS", "disable-sitemap-xml": "Изключване на картата на уеб сайта („Sitemap.xml“)", "sitemap-topics": "Брой теми за показване в картата на уеб сайта", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "Давност на кеша на картата на уеб сайт (часове)", "clear-sitemap-cache": "Изчистване на кеша на картата на уеб сайта", "view-sitemap": "Преглед на картата на уеб сайта" } \ No newline at end of file diff --git a/public/language/bg/aria.json b/public/language/bg/aria.json index ef88594736..f4c38d71b9 100644 --- a/public/language/bg/aria.json +++ b/public/language/bg/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "Наблюдавани от потребителя етикети", "delete-upload-button": "Бутон за изтриване на каченото", "group-page-link-for": "Връзка към груповата страница за %1", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "Показване на допълнителните публикации" } \ No newline at end of file diff --git a/public/language/bg/category.json b/public/language/bg/category.json index 72b561fb58..9783c1b61b 100644 --- a/public/language/bg/category.json +++ b/public/language/bg/category.json @@ -1,8 +1,8 @@ { "category": "Категория", "subcategories": "Подкатегории", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "Свят", + "uncategorized.description": "Теми произхождащи извън този форум. Преглежданията и мненията представени тук може да не са обвързани с този форум и членовете му.", "handle.description": "Тази категория може да бъде последвана от отворената социална мрежа от чрез идентификатора %1", "new-topic-button": "Нова тема", "guest-login-post": "Впишете се, за да можете да публикувате", diff --git a/public/language/bg/error.json b/public/language/bg/error.json index a1563ad26c..0df31d3df2 100644 --- a/public/language/bg/error.json +++ b/public/language/bg/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Грешни данни", + "invalid-config-field-value": "Неправилна стойност за конфигурационното поле „%1“: %2", "invalid-json": "Неправилен JSON", "wrong-parameter-type": "За свойството `%1` се очакваше стойност от тип %3, но вместо това беше получено %2", "required-parameters-missing": "Липсват задължителни параметри от това извикване към ППИ: %1", @@ -32,7 +33,7 @@ "invalid-path": "Грешен път", "folder-exists": "Вече има папка с това име", "invalid-pagination-value": "Грешен номер на странициране, трябва да бъде между %1 и %2", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "Грешна стойност за възрастта на публикациите, след която те не се показват в непрочетените – трябва да бъде между 1 и %1", "username-taken": "Потребителското име е заето", "email-taken": "Адресът на е-пощата вече е зает.", "email-nochange": "Въведената е-поща е същата като съществуващата.", diff --git a/public/language/bg/global.json b/public/language/bg/global.json index 1e85ec221a..7f16eab06e 100644 --- a/public/language/bg/global.json +++ b/public/language/bg/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "Разрешените файлови типове са: %1", "unsaved-changes": "Имате незапазени промени. Наистина ли искате да напуснете тази страница?", "reconnecting-message": "Изглежда връзката Ви към %1 беше прекъсната. Моля, изчакайте докато се опитаме да Ви свържем отново.", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "Повторното свързване с %1 е успешно.", "play": "Пускане", "cookies.message": "Този уеб сайт използва бисквитки, за да предостави услугите си по възможно най-добрия начин.", "cookies.accept": "Разбрано!", diff --git a/public/language/bg/groups.json b/public/language/bg/groups.json index e2eda68c47..fcab47ac6a 100644 --- a/public/language/bg/groups.json +++ b/public/language/bg/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "Група", "all-groups": "Всички групи", "groups": "Групи", "members": "Членове", - "x-members": "%1 member(s)", + "x-members": "%1 член(ове)", "view-group": "Преглед на групата", "owner": "Собственик на групата", "new-group": "Създаване на нова група", diff --git a/public/language/bg/login.json b/public/language/bg/login.json index 4914291c5c..1dd0452064 100644 --- a/public/language/bg/login.json +++ b/public/language/bg/login.json @@ -6,7 +6,7 @@ "alternative-logins": "Други начини за вписване", "failed-login-attempt": "Неуспешно вписване", "login-successful": "Вие влязохте успешно!", - "dont-have-account": "Нямате регистрация?", + "dont-have-account": "Нямате акаунт?", "logged-out-due-to-inactivity": "Вие излязохте автоматично от администраторския контролен панел, поради бездействие.", "caps-lock-enabled": "Главните букви са включени" } \ No newline at end of file diff --git a/public/language/bg/modules.json b/public/language/bg/modules.json index 59cada982b..a68c6685a8 100644 --- a/public/language/bg/modules.json +++ b/public/language/bg/modules.json @@ -82,7 +82,7 @@ "composer.hide-preview": "Скриване на прегледа", "composer.help": "Помощ", "composer.user-said-in": "%1 каза в %2:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [каза](%2):", "composer.discard": "Наистина ли искате да отхвърлите тази публикация?", "composer.submit-and-lock": "Публикуване и заключване", "composer.toggle-dropdown": "Превключване на падащото меню", diff --git a/public/language/bg/notifications.json b/public/language/bg/notifications.json index 18fb80f216..d61fa41bf3 100644 --- a/public/language/bg/notifications.json +++ b/public/language/bg/notifications.json @@ -65,7 +65,7 @@ "new-register-multiple": "Има %1 заявки за регистрация, които очакват да бъдат прегледани.", "flag-assigned-to-you": "Докладът %1 беше назначен на Вас", "post-awaiting-review": "Публикацията чака да бъде прегледана", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "Темата чака да бъде прегледана", "profile-exported": "Профилът на %1 е изнесен, щракнете за сваляне", "posts-exported": "Публикациите на %1 са изнесени, щракнете за сваляне", "uploads-exported": "Качванията на %1 са изнесени, щракнете за сваляне", diff --git a/public/language/bg/themes/harmony.json b/public/language/bg/themes/harmony.json index b66d55df79..a7ab555059 100644 --- a/public/language/bg/themes/harmony.json +++ b/public/language/bg/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Тема на Harmony", "skins": "Облици", - "light": "Light", - "dark": "Dark", + "light": "Светло", + "dark": "Тъмно", "collapse": "Свиване", "expand": "Разгъване", "sidebar-toggle": "Превключване на страничната лента", diff --git a/public/language/bg/topic.json b/public/language/bg/topic.json index 23dfc2495d..00bc76158f 100644 --- a/public/language/bg/topic.json +++ b/public/language/bg/topic.json @@ -225,7 +225,7 @@ "no-more-next-post": "Нямате повече публикации в тази тема", "open-composer": "Отваряне на редактора", "post-quick-reply": "Бърз отговор", - "post-quick-create": "Quick post", + "post-quick-create": "Бърза публикация", "navigator.index": "Публикация %1 от %2", "navigator.unread": "%1 непрочетени", "upvote-post": "Положително гласуване за публикацията", diff --git a/public/language/bg/user.json b/public/language/bg/user.json index bebdffe7f6..161a5e063e 100644 --- a/public/language/bg/user.json +++ b/public/language/bg/user.json @@ -146,8 +146,8 @@ "upvote-notif-freq.threshold": "на 1, 5, 10, 25, 50, 100, 150, 200…", "upvote-notif-freq.logarithmic": "На 10, 100, 1000…", "upvote-notif-freq.disabled": "Изключено", - "notification-type-web": "Web", - "notification-type-email": "Email", + "notification-type-web": "Уеб", + "notification-type-email": "Е-поща", "browsing": "Настройки за страниците", "unread.cutoff": "Възраст на публикациите, след която те не се показват в непрочетените (най-много %1 дни)", "unread.cutoff-help": "Темите ще се отбелязват като прочетени, ако в тях няма нови неща в рамките на посочения брой дни.", diff --git a/public/language/bg/world.json b/public/language/bg/world.json index 9da78356ee..6ca101eab0 100644 --- a/public/language/bg/world.json +++ b/public/language/bg/world.json @@ -1,12 +1,14 @@ { "name": "Свят", - "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", - "recent": "All", + "latest": "Най-нови", + "latest-local": "Най-нови (локални)", + "latest-all": "Най-нови (всички)", + "popular-day": "Популярни (за деня)", + "popular-week": "Популярни (за седмицата)", + "popular-month": "Популярни (за месеца)", + "popular-year": "Популярни (за годината)", + "popular-alltime": "Популярни (за всички времена)", + "recent": "Всички", "help": "Помощ", "help.title": "Каква е тази страница?", @@ -16,10 +18,12 @@ "help.federating": "По същия начин, ако потребители извън този форум започнат да следват Вас, тогава Вашите публикации ще започнат да се появяват в техните приложения и уеб сайтове.", "help.next-generation": "Това е новото поколение социална мрежа. Започнете да допринасяте още днес!", - "onboard.title": "Вашият прозорец към федивселената…", - "onboard.what": "Това е Вашата персонализирана категория съставена само от съдържание извън този форум. Тук се появяват неща от хора, които следвате, както и такива споделени от тях.", - "onboard.why": "Много неща се случват извън този форум, и не всичко отговаря на Вашите интереси. Затова следването на конкретни хора е най-добрият начин да покажете, че искате да виждате повече от тях.", - "onboard.how": "Междувременно можете да използвате бутоните в горната част, за да видите до какво има достъп този форум. Така може да започнете да откривате ново съдържание!", + "onboard.title": "Свят изпълнен със съдържание, на една ръка разстояние…", + "onboard.what": "Гледайте на това като на глобална опашка за откриване на съдържание. Тук се събират интересни дискусии от различни места в мрежата и от други общности – на едно място.", + "onboard.why": "Можете да разглеждате препоръчаните популярни теми, но най-добрият начин да ползвате тази функционалност, е да я нагласите по свой вкус. Ако си създадете акаунт, ще можете да следвате определени хора или теми – така ще филтрирате шума и ще виждате само това, което Ви интересува.", + "onboard.how": "Готови? Създайте си акаунт и започнете да следвате другите, да получавате известия когато хората Ви отговарят, както и да запазвате любимите си открития.", - "category-search": "Find a category..." + "category-search": "Търсене на категория…", + "see-more": "Вижте повече", + "see-less": "Вижте по-малко" } \ No newline at end of file diff --git a/public/language/bn/admin/advanced/jobs.json b/public/language/bn/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/bn/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/bn/admin/dashboard.json b/public/language/bn/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/bn/admin/dashboard.json +++ b/public/language/bn/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/bn/admin/manage/users.json b/public/language/bn/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/bn/admin/manage/users.json +++ b/public/language/bn/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/bn/admin/menu.json b/public/language/bn/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/bn/admin/menu.json +++ b/public/language/bn/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/bn/admin/settings/activitypub.json b/public/language/bn/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/bn/admin/settings/activitypub.json +++ b/public/language/bn/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/bn/admin/settings/general.json b/public/language/bn/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/bn/admin/settings/general.json +++ b/public/language/bn/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/bn/error.json b/public/language/bn/error.json index 097cc14d75..adabb0bc9f 100644 --- a/public/language/bn/error.json +++ b/public/language/bn/error.json @@ -1,5 +1,6 @@ { "invalid-data": "ভুল তথ্য", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/bn/world.json b/public/language/bn/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/bn/world.json +++ b/public/language/bn/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/cs/admin/advanced/events.json b/public/language/cs/admin/advanced/events.json index 19d44ec316..52ad908586 100644 --- a/public/language/cs/admin/advanced/events.json +++ b/public/language/cs/admin/advanced/events.json @@ -9,9 +9,9 @@ "filter-type": "Typ události", "filter-start": "Datum začátku", "filter-end": "Datum konce", - "filter-user": "Filter by User", - "filter-user.placeholder": "Type user name to filter...", - "filter-group": "Filter by Group", - "filter-group.placeholder": "Type group name to filter...", + "filter-user": "Filtrovat podle uživatele", + "filter-user.placeholder": "Zadejte uživatelské jméno pro filtrování…", + "filter-group": "Filtrovat podle skupiny", + "filter-group.placeholder": "Zadejte název skupiny pro filtrování...", "filter-per-page": "Na stránku" } \ No newline at end of file diff --git a/public/language/cs/admin/advanced/jobs.json b/public/language/cs/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/cs/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/cs/admin/dashboard.json b/public/language/cs/admin/dashboard.json index 047f6b5161..191cabfa61 100644 --- a/public/language/cs/admin/dashboard.json +++ b/public/language/cs/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Témata", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Posledních 7 dnů", "page-views-thirty": "Posledních 30 dní", "page-views-last-day": "Posledních 24 hodin", - "page-views-custom": "Dle rozsahu data", + "page-views-custom": "Custom Range", "page-views-custom-start": "Začátek rozsahu", "page-views-custom-end": "Konec rozsahu", "page-views-custom-help": "Zadejte rozsah data zobrazení stránek, které chcete vidět. Není-li datum nastaveno, výchozí formát je YYYY-MM-DD", diff --git a/public/language/cs/admin/extend/widgets.json b/public/language/cs/admin/extend/widgets.json index 5298775419..0f9a01f06c 100644 --- a/public/language/cs/admin/extend/widgets.json +++ b/public/language/cs/admin/extend/widgets.json @@ -12,8 +12,8 @@ "container.card": "Card", "container.card-header": "Card Header", "container.card-body": "Card Body", - "container.title": "Title", - "container.body": "Body", + "container.title": "Název", + "container.body": "Tělo", "container.alert": "Upozornění", "alert.confirm-delete": "Jste si jist/a, že chcete smazat tuto miniaplikaci?", @@ -32,6 +32,6 @@ "start-date": "Start date", "end-date": "End date", "hide-on-mobile": "Skrýt na mobilu", - "hide-drafts": "Hide drafts", - "show-drafts": "Show drafts" + "hide-drafts": "Schovat koncepty", + "show-drafts": "Zobrazit koncepty" } \ No newline at end of file diff --git a/public/language/cs/admin/manage/user-custom-fields.json b/public/language/cs/admin/manage/user-custom-fields.json index 354f23e52e..c3c2419998 100644 --- a/public/language/cs/admin/manage/user-custom-fields.json +++ b/public/language/cs/admin/manage/user-custom-fields.json @@ -2,27 +2,27 @@ "title": "Správa vlastních uživatelských polí", "create-field": "Vytvořit pole", "edit-field": "Upravit pole", - "manage-custom-fields": "Manage Custom Fields", - "type-of-input": "Type of input", - "key": "Key", - "name": "Name", - "icon": "Icon", - "type": "Type", - "min-rep": "Minimum Reputation", - "input-type-text": "Input (Text)", - "input-type-link": "Input (Link)", - "input-type-number": "Input (Number)", - "input-type-date": "Input (Date)", - "input-type-select": "Select", - "input-type-select-multi": "Select Multiple", - "select-options": "Options", - "select-options-help": "Add one option per line for the select element", - "minimum-reputation": "Minimum reputation", - "minimum-reputation-help": "If a user has less than this value they won't be able to use this field", - "delete-field-confirm-x": "Do you really want to delete custom field \"%1\"?", - "custom-fields-saved": "Custom fields saved", - "visibility": "Visibility", - "visibility-all": "Everyone can see the field", - "visibility-loggedin": "Only logged in users can see the field", - "visibility-privileged": "Only privileged users like admins & moderators can see the field" + "manage-custom-fields": "Správa vlastních polí", + "type-of-input": "Typ vstupu", + "key": "Klíč", + "name": "Jméno", + "icon": "Ikona", + "type": "Typ", + "min-rep": "Minimální reputace", + "input-type-text": "Vstup (Text)", + "input-type-link": "Vstup (Odkaz)", + "input-type-number": "Vstup (Číslo)", + "input-type-date": "Vstup (Datum)", + "input-type-select": "Vybrat", + "input-type-select-multi": "Vybrat více možností", + "select-options": "Možnosti", + "select-options-help": "Pro výběr přidejte každou možnost na samostatný řádek", + "minimum-reputation": "Minimální reputace", + "minimum-reputation-help": "Pokud má uživatel méně než tuto hodnotu, nebude moci toto pole používat", + "delete-field-confirm-x": "Opravdu chcete smazat vlastní pole \"%1“?", + "custom-fields-saved": "Vlastní pole uložena", + "visibility": "Viditelnost", + "visibility-all": "Pole může vidět každý", + "visibility-loggedin": "Pole mohou vidět pouze přihlášení uživatelé", + "visibility-privileged": "Pole mohou vidět pouze vybraní uživatelé, například administrátoři a moderátoři" } \ No newline at end of file diff --git a/public/language/cs/admin/manage/users.json b/public/language/cs/admin/manage/users.json index cd2af138b2..cba450a9ba 100644 --- a/public/language/cs/admin/manage/users.json +++ b/public/language/cs/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 na stránku", "500-per-page": "500 na stránku", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Dle ID uživatele", "search.uid-placeholder": "Pro hledání, zadejte ID uživatele", "search.username": "Dle jména uživatele", diff --git a/public/language/cs/admin/menu.json b/public/language/cs/admin/menu.json index a4ab204ff5..8a600c3310 100644 --- a/public/language/cs/admin/menu.json +++ b/public/language/cs/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Protokoly", "advanced/errors": "Chyby", "advanced/cache": "Mezipamě", + "advanced/jobs": "Jobs", "development/logger": "Protokolář", "development/info": "Informace", diff --git a/public/language/cs/admin/settings/activitypub.json b/public/language/cs/admin/settings/activitypub.json index 111cdfa472..7cbf3281c2 100644 --- a/public/language/cs/admin/settings/activitypub.json +++ b/public/language/cs/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/cs/admin/settings/general.json b/public/language/cs/admin/settings/general.json index 78c991a4f9..a5dcb3ef1e 100644 --- a/public/language/cs/admin/settings/general.json +++ b/public/language/cs/admin/settings/general.json @@ -15,10 +15,10 @@ "title-layout": "Vzhled názvu", "title-layout-help": "Určete jak název prohlížeče má být sestaven, tj. {pageTitle} | {browserTitle}", "description.placeholder": "Zkrácený popis vaší komunity", - "description": "Site Description", + "description": "Popis stránky", "keywords": "Klíčová slova pro stránky", "keywords-placeholder": "Klíčová slova popisující vaši komunitu, odděleno čárkou", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Obrázek", "logo.image-placeholder": "Cesta k logu, aby mohlo být zobrazeno v hlavičce fóra", "logo.upload": "Nahrát", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Odchozí odkazy", "outgoing-links.warning-page": "Použít stránku s upozorněním při odchozích odkazech", "search": "Search", @@ -51,7 +53,7 @@ "topic-tools": "Topic Tools", "home-page": "Domovská stránka", "home-page-route": "Cesta k domovské stránce", - "home-page-description": "Choose what page is shown when users navigate to the root URL of your forum.", + "home-page-description": "Vyberte, která stránka se zobrazí, když uživatelé přejdou na hlavní URL vašeho fóra.", "custom-route": "Upravit cestu", "allow-user-home-pages": "Povolit uživatelům domovské stránky", "home-page-title": "Titulka domovské stránky (výchozí „Domů”)", diff --git a/public/language/cs/admin/settings/navigation.json b/public/language/cs/admin/settings/navigation.json index a4ad7fe1dc..9382245431 100644 --- a/public/language/cs/admin/settings/navigation.json +++ b/public/language/cs/admin/settings/navigation.json @@ -10,7 +10,7 @@ "id": "ID: doporučené", "properties": "Vlastnosti:", - "show-to-groups": "Show to Groups:", + "show-to-groups": "Ukázat skupinám:", "open-new-window": "Otevřít v novém okně", "dropdown": "Dropdown", "dropdown-placeholder": "Place your dropdown menu items below, ie:
<li><a class="dropdown-item" href="https://myforum.com">Link 1</a></li>", diff --git a/public/language/cs/admin/settings/post.json b/public/language/cs/admin/settings/post.json index 5b757e31de..d4d77fdb40 100644 --- a/public/language/cs/admin/settings/post.json +++ b/public/language/cs/admin/settings/post.json @@ -5,7 +5,7 @@ "sorting.oldest-to-newest": "Od nejstarších po nejnovější", "sorting.newest-to-oldest": "Od nejnovějších po nejstarší", "sorting.recently-replied": "Poslední příspěvky", - "sorting.recently-created": "Recently Created", + "sorting.recently-created": "Nedávno vytvořené", "sorting.most-votes": "Dle počtu hlasů", "sorting.most-posts": "Dle počtu příspěvků", "sorting.most-views": "Nejvíce zobrazení", diff --git a/public/language/cs/admin/settings/reputation.json b/public/language/cs/admin/settings/reputation.json index 10b3cb6617..162d4c8ef0 100644 --- a/public/language/cs/admin/settings/reputation.json +++ b/public/language/cs/admin/settings/reputation.json @@ -2,14 +2,14 @@ "reputation": "Nastavení reputace", "disable": "Zakázat systém reputace", "disable-down-voting": "Zakázat hlasování", - "upvote-visibility": "Up Vote visibility", - "upvote-visibility-all": "Everyone can see up votes", - "upvote-visibility-loggedin": "Only logged in users can see up votes", - "upvote-visibility-privileged": "Only privileged users like admins & moderators can see up votes", - "downvote-visibility": "Down Vote visibility", - "downvote-visibility-all": "Everyone can see down votes", - "downvote-visibility-loggedin": "Only logged in users can see down votes", - "downvote-visibility-privileged": "Only privileged users like admins & moderators can see down votes", + "upvote-visibility": "Viditelnost kladných hlasů", + "upvote-visibility-all": "Všichni mohou vidět kladné hlasy", + "upvote-visibility-loggedin": "Pouze přihlášení uživatelé mohou vidět kladné hlasy", + "upvote-visibility-privileged": "Kladné hlasy mohou vidět pouze vybraní uživatelé, jako jsou administrátoři a moderátoři", + "downvote-visibility": "Viditelnost záporných hlasů", + "downvote-visibility-all": "Všichni mohou vidět záporné hlasy", + "downvote-visibility-loggedin": "Pouze přihlášení uživatelé mohou vidět záporné hlasy", + "downvote-visibility-privileged": "Záporné hlasy mohou vidět pouze vybraní uživatelé, jako jsou administrátoři a moderátoři", "thresholds": "Omezení aktivity", "min-rep-upvote": "Minimum reputation to upvote posts", "upvotes-per-day": "Upvotes per day (set to 0 for unlimited upvotes)", @@ -29,12 +29,12 @@ "flags.limit-per-target": "Maximum number of times something can be flagged", "flags.limit-per-target-placeholder": "Default: 0", "flags.limit-per-target-help": "When a post or user is flagged multiple times, each additional flag is considered a "report" and added to the original flag. Set this option to a number other than zero to limit the number of reports an item can receive.", - "flags.limit-post-flags-per-day": "Maximum number of times a user can flag posts in a day", - "flags.limit-post-flags-per-day-help": "Set to 0 to disable, (default: 10)", - "flags.limit-user-flags-per-day": "Maximum number of times a user can flag users in a day", - "flags.limit-user-flags-per-day-help": "Set to 0 to disable, (default: 10)", - "flags.auto-flag-on-downvote-threshold": "Number of downvotes to auto flag posts", - "flags.auto-flag-on-downvote-threshold-help": "Set to 0 to disable, (default: 0)", + "flags.limit-post-flags-per-day": "Maximální počet označení příspěvků uživatelem za den", + "flags.limit-post-flags-per-day-help": "Nastavte na 0 pro deaktivaci (výchozí: 10)", + "flags.limit-user-flags-per-day": "Maximální počet označení uživatelů jedním uživatelem za den", + "flags.limit-user-flags-per-day-help": "Nastavte na 0 pro deaktivaci (výchozí: 10)", + "flags.auto-flag-on-downvote-threshold": "Počet záporných hlasů pro automatické označení příspěvků", + "flags.auto-flag-on-downvote-threshold-help": "Nastavte na 0 pro deaktivaci (výchozí: 10)", "flags.auto-resolve-on-ban": "Automatically resolve all of a user's tickets when they are banned", "flags.action-on-resolve": "Do the following when a flag is resolved", "flags.action-on-reject": "Do the following when a flag is rejected", diff --git a/public/language/cs/admin/settings/user.json b/public/language/cs/admin/settings/user.json index ec85df9d73..c5d81e2795 100644 --- a/public/language/cs/admin/settings/user.json +++ b/public/language/cs/admin/settings/user.json @@ -64,7 +64,7 @@ "show-email": "Zobrazit e-mail", "show-fullname": "Zobrazit celé jméno", "restrict-chat": "Povolit chatové zprávy jen od uživatelů, které sleduji", - "disable-incoming-chats": "Disable incoming chat messages", + "disable-incoming-chats": "Zakázat příchozí zprávy v chatu", "outgoing-new-tab": "Otevřít odchozí odkazy v nové záložce", "topic-search": "Povolit hledání v tématu", "update-url-with-post-index": "Update url with post index while browsing topics", diff --git a/public/language/cs/email.json b/public/language/cs/email.json index 58905248b9..633b280fb3 100644 --- a/public/language/cs/email.json +++ b/public/language/cs/email.json @@ -36,8 +36,8 @@ "digest.title.day": "Váš denní přehled", "digest.title.week": "Váš týdenní přehled", "digest.title.month": "Váš měsíční přehled", - "notif.chat.new-message-from-user": "New message from \"%1\"", - "notif.chat.new-message-from-user-in-room": "New message from %1 in room %2", + "notif.chat.new-message-from-user": "Nová zpráva od \"%1\"", + "notif.chat.new-message-from-user-in-room": "Nová zpráva od %1 v místnosti %2", "notif.chat.cta": "Chcete-li pokračovat v konverzaci, klikněte zde.", "notif.chat.unsub.info": "Toto upozornění na chat vám bylo odesláno na základě vašeho nastavení odběru.", "notif.post.unsub.info": "Toto upozornění na příspěvek vám bylo odesláno na základě vašeho nastavení odběru.", diff --git a/public/language/cs/error.json b/public/language/cs/error.json index 39be176dfb..29e104ec70 100644 --- a/public/language/cs/error.json +++ b/public/language/cs/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Neplatná data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Neplatný JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/cs/flags.json b/public/language/cs/flags.json index 5defdb2338..8512b422b2 100644 --- a/public/language/cs/flags.json +++ b/public/language/cs/flags.json @@ -1,6 +1,6 @@ { "state": "Stav", - "report": "Report", + "report": "Hlášení", "reports": "Reports", "first-reported": "First Reported", "no-flags": "Hurá, žádné označení.", @@ -9,8 +9,8 @@ "update": "Aktualizovat", "updated": "Aktualizováno", "resolved": "Resolved", - "report-added": "Added", - "report-rescinded": "Rescinded", + "report-added": "Přidáno", + "report-rescinded": "Zrušeno", "target-purged": "Obsah, na který se toto označení vztahuje, byl vymazán a již není k dispozici.", "target-aboutme-empty": "This user has no "About Me" set.", @@ -84,18 +84,18 @@ "modal-reason-offensive": "Urážlivé", "modal-reason-other": "Jiné (popište níže)", "modal-reason-custom": "Důvod ohlášení tohoto obsahu…", - "modal-notify-remote": "Forward this report to %1", + "modal-notify-remote": "Přeposlat toto hlášení na %1", "modal-submit": "Předat hlášení", "modal-submit-success": "Obsah byl označen pro moderaci.", - "modal-confirm-rescind": "Rescind Report?", + "modal-confirm-rescind": "Zrušit hlášení?", "bulk-actions": "Bulk Actions", "bulk-resolve": "Resolve Flag(s)", - "confirm-purge": "Are you sure you want to permanently delete these flags?", - "purge-cancelled": "Flag Purge Cancelled", - "bulk-purge": "Purge Flag(s)", + "confirm-purge": "Opravdu chcete trvale smazat tato označení?", + "purge-cancelled": "Mazání označení zrušeno", + "bulk-purge": "Odstranit označení", "bulk-success": "%1 flags updated", - "flagged-timeago": "Flagged ", + "flagged-timeago": "Označeno ", "auto-flagged": "[Auto Flagged] Received %1 downvotes." } \ No newline at end of file diff --git a/public/language/cs/pages.json b/public/language/cs/pages.json index 1d51c7ef47..95a825f897 100644 --- a/public/language/cs/pages.json +++ b/public/language/cs/pages.json @@ -36,7 +36,7 @@ "chat": "Konverzace s %1", "flags": "Označení", "flag-details": "Detaily označení %1", - "world": "World", + "world": "Svět", "account/edit": "Úprava \"%1\"", "account/edit/password": "Úprava hesla \"%1\"", "account/edit/username": "Úprava jména uživatele \"%1\"", @@ -55,7 +55,7 @@ "account/settings-of": "Changing settings of %1", "account/watched": "Témata sledovaná uživatelem %1", "account/ignored": "Témata ignorovaná uživatelem %1", - "account/read": "Topics read by %1", + "account/read": "Témata přečtená uživatelem %1", "account/upvoted": "Souhlasí s příspěvkem %1", "account/downvoted": "Nesouhlasí s příspěvkem %1", "account/best": "Nejlepší příspěvky od %1", @@ -63,9 +63,9 @@ "account/blocks": "Zablokovaní uživatelé z %1", "account/uploads": "Nahráno od %1", "account/sessions": "Relace s přihlášením", - "account/shares": "Topics shared by %1", + "account/shares": "Témata sdílená uživatelem %1", "confirm": "E-mail potvrzen", - "maintenance.text": "%1 is currently undergoing maintenance.
Please come back another time.", + "maintenance.text": "%1 je momentálně v údržbě.
Prosím, vraťte se později.", "maintenance.messageIntro": "Správce zanechal tuto zprávu:", "throttled.text": "%1 je v současnou chvíli nedostupný pro velkou zátěž. Zkuste to později." } \ No newline at end of file diff --git a/public/language/cs/post-queue.json b/public/language/cs/post-queue.json index e3e410fb22..c2efa38317 100644 --- a/public/language/cs/post-queue.json +++ b/public/language/cs/post-queue.json @@ -3,10 +3,10 @@ "post-queue": "Fronta příspěvků", "no-queued-posts": "There are no posts in the post queue.", "no-single-post": "The topic or post you are looking for is no longer in the queue. It has likely been approved or deleted already.", - "enabling-help": "The post queue is currently disabled. To enable this feature, go to Settings → Post → Post Queue and enable Post Queue.", + "enabling-help": "Fronta příspěvků je momentálně zakázána. Chcete-li tuto funkci povolit, přejděte do Nastavení → Příspěvek → Fronta příspěvků a zapněte Frontu příspěvků.", "back-to-list": "Back to Post Queue", - "public-intro": "If you have any queued posts, they will be shown here.", - "public-description": "This forum is configured to automatically queue posts from new accounts, pending moderator approval.
If you have queued posts awaiting approval, you will be able to see them here.", + "public-intro": "Pokud máte nějaké příspěvky ve frontě, budou zde zobrazeny.", + "public-description": "Toto fórum je nastaveno tak, aby automaticky zařazovalo příspěvky od nových účtů do fronty čekající na schválení moderátorem.
Pokud máte příspěvky ve frontě čekající na schválení, uvidíte je zde.", "user": "Uživatel", "when": "When", "category": "Kategorie", @@ -39,5 +39,5 @@ "remove-selected-confirm": "Do you want to remove %1 selected posts?", "bulk-accept-success": "%1 posts accepted", "bulk-reject-success": "%1 posts rejected", - "links-in-this-post": "Links in this post" + "links-in-this-post": "Odkazy v tomto příspěvku" } \ No newline at end of file diff --git a/public/language/cs/recent.json b/public/language/cs/recent.json index 4bd5eec576..e4b9c65071 100644 --- a/public/language/cs/recent.json +++ b/public/language/cs/recent.json @@ -8,6 +8,6 @@ "no-recent-topics": "Nebyly nalezeny žádné nové téma.", "no-popular-topics": "Žádná oblíbená téma.", "load-new-posts": "Load new posts", - "uncategorized.title": "All known topics", - "uncategorized.intro": "This page shows a chronological listing of every topic that this forum has received.
The views and opinions expressed in the topics below are not moderated and may not represent the views and opinions of this website." + "uncategorized.title": "Všechny známá témata", + "uncategorized.intro": "Tato stránka zobrazuje chronologický seznam všech témat, která toto fórum obdrželo.
Názory a postoje vyjádřené v níže uvedených tématech nejsou moderovány a nemusí odrážet názory tohoto webu." } \ No newline at end of file diff --git a/public/language/cs/rewards.json b/public/language/cs/rewards.json index f923cf1500..d35552949a 100644 --- a/public/language/cs/rewards.json +++ b/public/language/cs/rewards.json @@ -1,10 +1,10 @@ { - "awarded-x-reputation": "You have been awarded %1 reputation", - "awarded-group-membership": "You have been added to the group %1", + "awarded-x-reputation": "Byla vám přidělena %1 reputace", + "awarded-group-membership": "Byli jste přidáni do skupiny %1", - "essentials/user.reputation-conditional-value": "(Reputation %1 %2)", - "essentials/user.postcount-conditional-value": "(Post Count %1 %2)", - "essentials/user.lastonline-conditional-value": "(Last Online %1 %2)", - "essentials/user.joindate-conditional-value": "(Join Date %1 %2)", - "essentials/user.daysregistered-conditional-value": "(Days Registered %1 %2)" + "essentials/user.reputation-conditional-value": "(Reputace %1 %2)", + "essentials/user.postcount-conditional-value": "(Počet příspěvků %1 %2)", + "essentials/user.lastonline-conditional-value": "(Poslední připojení %1 %2)", + "essentials/user.joindate-conditional-value": "(Datum registrace %1 %2)", + "essentials/user.daysregistered-conditional-value": "(Dny od registrace %1 %2)" } \ No newline at end of file diff --git a/public/language/cs/search.json b/public/language/cs/search.json index 4a364aefa7..d949f1efbb 100644 --- a/public/language/cs/search.json +++ b/public/language/cs/search.json @@ -1,42 +1,42 @@ { - "type-to-search": "Type to search", + "type-to-search": "Začněte psát pro hledání", "results-matching": "Počet výsledků pro „%2“: %1, (%3 sekund)", "no-matches": "Nic nebylo nalezeno", "advanced-search": "Pokročilé hledání", "in": "v", - "in-titles": "In titles", - "in-titles-posts": "In titles and posts", - "in-posts": "In posts", - "in-bookmarks": "In bookmarks", - "in-categories": "In categories", - "in-users": "In users", - "in-tags": "In tags", + "in-titles": "V názvech", + "in-titles-posts": "V názvech a příspěvcích", + "in-posts": "V příspěvcích", + "in-bookmarks": "V záložkách", + "in-categories": "V kategoriích", + "in-users": "V uživatelích", + "in-tags": "Ve štítcích", "categories": "Kategorie", - "all-categories": "All categories", - "categories-x": "Categories: %1", - "categories-watched-categories": "Categories: Watched categories", - "type-a-category": "Type a category", + "all-categories": "Všechny kategorie", + "categories-x": "Kategorie: %1", + "categories-watched-categories": "Kategorie: Sledované kategorie", + "type-a-category": "Zadejte kategorii", "tags": "Štítky", - "tags-x": "Tags: %1", - "type-a-tag": "Type a tag", + "tags-x": "Štítky: %1", + "type-a-tag": "Zadejte štítek", "match-words": "Shodná slova", "match-all-words": "Match all words", "match-any-word": "Match any word", "all": "Vše", "any": "Jakékoliv", "posted-by": "Napsal", - "posted-by-usernames": "Posted by: %1", - "type-a-username": "Type a username", + "posted-by-usernames": "Publikoval: %1", + "type-a-username": "Zadejte uživatelské jméno", "search-child-categories": "Hledat podružné kategorie", "has-tags": "Obsahuje značky", "reply-count": "Počet odpovědí", - "replies": "Replies", - "replies-atleast-count": "Replies: At least %1", - "replies-atmost-count": "Replies: At most %1", + "replies": "Odpovědi", + "replies-atleast-count": "Odpovědi: Alespoň %1", + "replies-atmost-count": "Odpovědi: Maximálně %1", "at-least": "Nejméně", "at-most": "Nejvíce", "relevance": "Relevantnost", - "time": "Time", + "time": "Čas", "post-time": "Čas příspěvku", "votes": "Hlasů", "newer-than": "Novější než", @@ -49,22 +49,22 @@ "three-months": "Tři měsíce", "six-months": "Šest měsíců", "one-year": "Jeden rok", - "time-newer-than-86400": "Time: Newer than yesterday", - "time-older-than-86400": "Time: Older than yesterday", - "time-newer-than-604800": "Time: Newer than one week", - "time-older-than-604800": "Time: Older than one week", - "time-newer-than-1209600": "Time: Newer than two weeks", - "time-older-than-1209600": "Time: Older than two weeks", - "time-newer-than-2592000": "Time: Newer than one month", - "time-older-than-2592000": "Time: Older than one month", - "time-newer-than-7776000": "Time: Newer than three months", - "time-older-than-7776000": "Time: Older than three months", - "time-newer-than-15552000": "Time: Newer than six months", - "time-older-than-15552000": "Time: Older than six months", - "time-newer-than-31104000": "Time: Newer than one year", - "time-older-than-31104000": "Time: Older than one year", + "time-newer-than-86400": "Čas: Novější než včera", + "time-older-than-86400": "Čas: Starší než včera", + "time-newer-than-604800": "Čas: Novější než jeden týden", + "time-older-than-604800": "Čas: Starší než jeden týden", + "time-newer-than-1209600": "Čas: Novější než dva týdny", + "time-older-than-1209600": "Čas: Starší než dva týdny", + "time-newer-than-2592000": "Čas: Novější než jeden měsíc", + "time-older-than-2592000": "Čas: Starší než jeden měsíc", + "time-newer-than-7776000": "Čas: Novější než tři měsíce", + "time-older-than-7776000": "Čas: Starší než tři měsíce", + "time-newer-than-15552000": "Čas: Novější než šest měsíců", + "time-older-than-15552000": "Čas: Starší než šest měsíců", + "time-newer-than-31104000": "Čas: Novější než jeden rok", + "time-older-than-31104000": "Čas: Starší než jeden rok", "sort-by": "Řadit dle", - "sort": "Sort", + "sort": "Řadit", "last-reply-time": "Čas poslední odpovědi", "topic-title": "Název tématu", "topic-votes": "Hlasy tématu", @@ -97,14 +97,14 @@ "sort-by-user.username-asc": "Sort by: Username in ascending order", "sort-by-category.name-desc": "Sort by: Category in descending order", "sort-by-category.name-asc": "Sort by: Category in ascending order", - "save": "Save", + "save": "Uložit", "save-preferences": "Uložit nastavení", "clear-preferences": "Smazat nastavení", "search-preferences-saved": "Hledat dle uložených nastavení", "search-preferences-cleared": "Hledat dle smazaných nastavení", "show-results-as": "Zobrazit výsledek jako", - "show-results-as-topics": "Show results as topics", - "show-results-as-posts": "Show results as posts", + "show-results-as-topics": "Zobrazit výsledky jako témata", + "show-results-as-posts": "Zobrazit výsledky jako příspěvky", "see-more-results": "Zobrazit více výsledků (%1)", - "search-in-category": "Search in \"%1\"" + "search-in-category": "Hledat v \"%1\"" } \ No newline at end of file diff --git a/public/language/cs/social.json b/public/language/cs/social.json index 5b8dd99a46..f8ee1fb2f2 100644 --- a/public/language/cs/social.json +++ b/public/language/cs/social.json @@ -1,14 +1,14 @@ { - "sign-in-with-twitter": "Sign in with Twitter", - "sign-up-with-twitter": "Sign up with Twitter", - "sign-in-with-github": "Sign in with Github", - "sign-up-with-github": "Sign up with Github", - "sign-in-with-google": "Sign in with Google", - "sign-up-with-google": "Sign up with Google", - "log-in-with-facebook": "Log in with Facebook", - "continue-with-facebook": "Continue with Facebook", - "sign-in-with-linkedin": "Sign in with LinkedIn", - "sign-up-with-linkedin": "Sign up with LinkedIn", - "sign-in-with-wordpress": "Sign in with WordPress", - "sign-up-with-wordpress": "Sign up with WordPress" + "sign-in-with-twitter": "Přihlásit se pomocí Twitteru", + "sign-up-with-twitter": "Registrovat se pomocí Twitteru", + "sign-in-with-github": "Přihlásit se pomoci Github", + "sign-up-with-github": "Registrovat se pomocí Github", + "sign-in-with-google": "Přihlásit se pomocí Google", + "sign-up-with-google": "Registrovat se pomocí Google", + "log-in-with-facebook": "Přihlásit se pomocí Facebooku", + "continue-with-facebook": "Pokračovat pomocí Facebooku", + "sign-in-with-linkedin": "Přihlásit se pomocí LinkedIn", + "sign-up-with-linkedin": "Registrovat se pomocí LinkedIn", + "sign-in-with-wordpress": "Přihlásit se pomocí WordPressu", + "sign-up-with-wordpress": "Registrovat se pomocí WordPressu" } \ No newline at end of file diff --git a/public/language/cs/success.json b/public/language/cs/success.json index b1f996e509..213b3988e3 100644 --- a/public/language/cs/success.json +++ b/public/language/cs/success.json @@ -1,7 +1,7 @@ { "success": "Úspěšné", "topic-post": "Příspěvek úspěšně přidán.", - "post-queued": "Your post is queued for approval. You will get a notification when it is accepted or rejected.", + "post-queued": "Váš příspěvek je zařazen do fronty ke schválení. Obdržíte oznámení, až bude přijat nebo zamítnut.", "authentication-successful": "Úspěšné přihlášení", "settings-saved": "Nastavení byla uložena." } \ No newline at end of file diff --git a/public/language/cs/tags.json b/public/language/cs/tags.json index f6c6f0af11..bc6b27bca2 100644 --- a/public/language/cs/tags.json +++ b/public/language/cs/tags.json @@ -1,17 +1,17 @@ { - "all-tags": "All tags", + "all-tags": "Všechny štítky", "no-tag-topics": "Není zde žádné téma s tímto označením.", - "no-tags-found": "No tags found", + "no-tags-found": "Nenalezeny žádné štítky", "tags": "Štítky", - "enter-tags-here": "Enter tags, %1 - %2 characters.", + "enter-tags-here": "Zadejte štítky, %1 - %2 znaků.", "enter-tags-here-short": "Zadejte štítky…", "no-tags": "Zatím tu není žádné označení.", - "select-tags": "Select Tags", - "tag-whitelist": "Tag Whitelist", - "watching": "Watching", - "not-watching": "Not Watching", - "watching.description": "Notify me of new topics.", - "not-watching.description": "Do not notify me of new topics.", - "following-tag.message": "You will now be receiving notifications when somebody posts a topic with this tag.", - "not-following-tag.message": "You will not receive notifications when somebody posts a topic with this tag." + "select-tags": "Vybrat štítky", + "tag-whitelist": "Whitelist štítek", + "watching": "Sleduji", + "not-watching": "Nesleduji", + "watching.description": "Upozorni mě na nová témata", + "not-watching.description": "Neupozorňuj mě na nová témata.", + "following-tag.message": "Nyní budete dostávat upozornění pokud někdo přidá téma s tímto štítkem.", + "not-following-tag.message": "Nebudete dostávat upozornění pokud někdo přidá téma s tímto štítkem." } \ No newline at end of file diff --git a/public/language/cs/top.json b/public/language/cs/top.json index 6e1e05674e..9695bebe70 100644 --- a/public/language/cs/top.json +++ b/public/language/cs/top.json @@ -1,4 +1,4 @@ { - "title": "Top", - "no-top-topics": "No top topics" + "title": "Hlavní", + "no-top-topics": "Žádná hlavní témata" } \ No newline at end of file diff --git a/public/language/cs/users.json b/public/language/cs/users.json index 9ebf1bee91..b54c93aa41 100644 --- a/public/language/cs/users.json +++ b/public/language/cs/users.json @@ -1,6 +1,6 @@ { "all-users": "Všichni uživatelé", - "followed-users": "Followed Users", + "followed-users": "Sledovaní uživatelé", "latest-users": "Nejnovější uživatelé", "top-posters": "Nejaktivnější", "most-reputation": "Nejváženější", diff --git a/public/language/cs/world.json b/public/language/cs/world.json index d1f602f306..c2ccc649f9 100644 --- a/public/language/cs/world.json +++ b/public/language/cs/world.json @@ -1,6 +1,8 @@ { "name": "Svět", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Stejně tak, pokud vás začnou sledovat uživatelé mimo toto fórum, vaše příspěvky se začnou zobrazovat i v těchto aplikacích a na webových stránkách.", "help.next-generation": "Toto je nová generace sociálních sítí – začněte přispívat ještě dnes!", - "onboard.title": "Vaše okno do fediverse…", - "onboard.what": "Toto je vaše personalizovaná kategorie složená pouze z obsahu nalezeného mimo toto fórum. To, zda se něco zobrazí na této stránce, závisí na tom, zda tyto zdroje sledujete, nebo zda byl příspěvek sdílen někým, koho sledujete.", - "onboard.why": "Mimo toto fórum se děje spousta věcí, a ne všechno je relevantní pro vaše zájmy. Proto je sledování lidí nejlepší způsob, jak naznačit, že chcete vidět více obsahu od konkrétní osoby.", - "onboard.how": "Mezitím můžete kliknout na tlačítka zkratek nahoře, abyste viděli o čem dalším toto fórum ví, a začít objevovat nový obsah!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/da/admin/advanced/jobs.json b/public/language/da/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/da/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/da/admin/dashboard.json b/public/language/da/admin/dashboard.json index 7fe8831bea..ae6cccf29f 100644 --- a/public/language/da/admin/dashboard.json +++ b/public/language/da/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/da/admin/manage/users.json b/public/language/da/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/da/admin/manage/users.json +++ b/public/language/da/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/da/admin/menu.json b/public/language/da/admin/menu.json index c3cbc7445e..d3f13ce83c 100644 --- a/public/language/da/admin/menu.json +++ b/public/language/da/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/da/admin/settings/activitypub.json b/public/language/da/admin/settings/activitypub.json index f5726b8b58..49819c963e 100644 --- a/public/language/da/admin/settings/activitypub.json +++ b/public/language/da/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/da/admin/settings/general.json b/public/language/da/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/da/admin/settings/general.json +++ b/public/language/da/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/da/error.json b/public/language/da/error.json index 13a9672265..d0dc1bbc1a 100644 --- a/public/language/da/error.json +++ b/public/language/da/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ugyldig Data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/da/world.json b/public/language/da/world.json index 32e1b2af70..3637ccc7b0 100644 --- a/public/language/da/world.json +++ b/public/language/da/world.json @@ -1,6 +1,8 @@ { "name": "Verden", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Ligeså, hvis brugere udefra dette fourm begynder at følge dig, så vil dine opslag begynde at dukke op på deres programmer og hjemmesider også.", "help.next-generation": "Dette er den næste generation af sociale medier, bliv en del af det i dag!", - "onboard.title": "Dit vindue til fødiverset...", - "onboard.what": "Dette er din personaliserede kategori som består kun af indhold fra udefra dette forum. Om noget dukker op her eller ej afhænger af om følger personen der lavede indlægget, eller om du følger nogen der har fremhævet indlægget.", - "onboard.why": "Der foregår en masse udenfor dette forum, og ikke det hele er relevant for dine interesser. At følge folk er derfor den bedste måde at signalere at du gerne vil se mere fra dem.", - "onboard.how": "I mellemtiden kan du klikke på genvejs-knapperne i toppen for at se, hvad forummet kender til og begynd at opdage nyt indhold!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/de/admin/advanced/events.json b/public/language/de/admin/advanced/events.json index b31278c8b2..40a5566bd9 100644 --- a/public/language/de/admin/advanced/events.json +++ b/public/language/de/admin/advanced/events.json @@ -10,8 +10,8 @@ "filter-start": "Anfangsdatum", "filter-end": "Enddatum", "filter-user": "Nach Benutzer filtern", - "filter-user.placeholder": "Type user name to filter...", + "filter-user.placeholder": "Nutzername eingeben zum Filtern...", "filter-group": "Nach Gruppe filtern", - "filter-group.placeholder": "Type group name to filter...", + "filter-group.placeholder": "Gruppenname eingeben zum Filtern...", "filter-per-page": "Pro Seite" } \ No newline at end of file diff --git a/public/language/de/admin/advanced/jobs.json b/public/language/de/admin/advanced/jobs.json new file mode 100644 index 0000000000..73530000f9 --- /dev/null +++ b/public/language/de/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Jobname", + "schedule": "Zeitplan", + "next-run": "Nächster Lauf", + "last-duration": "Letzte Dauer", + "running": "Laufend", + "active": "Aktiv" +} \ No newline at end of file diff --git a/public/language/de/admin/dashboard.json b/public/language/de/admin/dashboard.json index e2f13acbb7..d0f31417d2 100644 --- a/public/language/de/admin/dashboard.json +++ b/public/language/de/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "Neue Benutzer", "posts": "Beiträge", "topics": "Themen", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "Remote-Beiträge", + "remote-topics": "Remote-Themen", + "messages": "Nachrichten", "page-views-seven": "Letzte 7 Tage", "page-views-thirty": "Letzte 30 Tage", "page-views-last-day": "Letzte 24 Stunden", - "page-views-custom": "Benutzerdefinierter Zeitraum", + "page-views-custom": "Benutzerdefinierter Bereich", "page-views-custom-start": "Anfang Zeitraum", "page-views-custom-end": "Ende Zeitraum", "page-views-custom-help": "Gebe einen Datumsbereich für Seitenaufrufe ein, die du anzeigen möchtest. Wenn keine Datumsauswahl verfügbar ist, ist das akzeptierte Format YYYY-MM-DD", diff --git a/public/language/de/admin/development/info.json b/public/language/de/admin/development/info.json index 062f425547..2b929ccb3b 100644 --- a/public/language/de/admin/development/info.json +++ b/public/language/de/admin/development/info.json @@ -1,14 +1,14 @@ { - "you-are-on": "Sie verwenden %1:%2", + "you-are-on": "Du verwendest %1:%2", "ip": "IP%1", "nodes-responded": "%1 Knoten antworteten innerhalb von %2ms", "host": "Host", - "primary": "primary / jobs", + "primary": "primär / Jobs", "pid": "PID", "nodejs": "Node.js Version", "online": "Online", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "rss/heap verwendet", "system-memory": "System-Speicher", "used-memory-process": "Verwendeter Prozess-Speicher", "used-memory-os": "Verwendeter System-Speicher", diff --git a/public/language/de/admin/extend/widgets.json b/public/language/de/admin/extend/widgets.json index c96f31cda3..bdd0ead2fa 100644 --- a/public/language/de/admin/extend/widgets.json +++ b/public/language/de/admin/extend/widgets.json @@ -13,7 +13,7 @@ "container.card-header": "Karten-Kopfzeile", "container.card-body": "Karten-Körper", "container.title": "Titel", - "container.body": "Body", + "container.body": "Körper", "container.alert": "Alarm", "alert.confirm-delete": "Möchtest Du dieses Widget wirklich löschen?", diff --git a/public/language/de/admin/manage/categories.json b/public/language/de/admin/manage/categories.json index 0d2d4b8ce9..4d49d2b70b 100644 --- a/public/language/de/admin/manage/categories.json +++ b/public/language/de/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "Kategorie auswählen", "set-parent-category": "Übergeordnete Kategorie festlegen", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "In diesem Abschnitt kannst du die Zugriffsrechte für Teile der Website einrichten. Rechte können für einzelne Benutzer oder ganze Gruppen vergeben werden.", "privileges.category-selector": "Konfiguriere Privilegien für", "privileges.warning": "Hinweis: Die Zugriffsberechtigungen werden sofort wirksam. Es ist nicht notwendig, die Kategorie zu speichern, nachdem du die Einstellungen angepasst hast.", "privileges.section-viewing": "Ansichtsberechtigungen", diff --git a/public/language/de/admin/manage/custom-reasons.json b/public/language/de/admin/manage/custom-reasons.json index 90a2e620af..b13b52b40f 100644 --- a/public/language/de/admin/manage/custom-reasons.json +++ b/public/language/de/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "title": "Benutzerdefinierte Gründe verwalten", + "create-reason": "Grund erstellen", + "edit-reason": "Grund bearbeiten", + "reasons-help": "Gründe sind vordefinierte Erklärungen, die benutzt werden, wenn man Nutzer sperrt oder stummschaltet oder wenn man Beiträge in der Beitragswarteschlange ablehnt.", + "reason-title": "Titel", + "reason-type": "Typ", + "reason-body": "Körper", + "reason-all": "Alle", + "reason-ban": "Sperren", + "reason-mute": "Stummschalten", + "reason-post-queue": "Beitrags-Warteschlange", + "reason-type-help": "Die Art der Aktion, für die dieser Grund gilt. Wenn 'Alle' ausgewählt ist, gilt dieser Grund für alle Aktionstypen.", + "custom-reasons-saved": "Benutzerdefinierte Gründe erfolgreich gespeichert", + "delete-reason-confirm-x": "Bist du sicher, dass du den benutzerdefinierten Grund mit dem Titel %1löschen willst? " } \ No newline at end of file diff --git a/public/language/de/admin/manage/privileges.json b/public/language/de/admin/manage/privileges.json index 40fe8e7fd3..ab4f02f865 100644 --- a/public/language/de/admin/manage/privileges.json +++ b/public/language/de/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "Themenzutritt", "create-topics": "Themen erstellen", "reply-to-topics": "Auf Themen antworten", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "Cross-Post-Themen", "schedule-topics": "Geplante Themen", "tag-topics": "Themen taggen", "edit-posts": "Beiträge editieren", diff --git a/public/language/de/admin/manage/user-custom-fields.json b/public/language/de/admin/manage/user-custom-fields.json index e5091d7219..fa1099f4c1 100644 --- a/public/language/de/admin/manage/user-custom-fields.json +++ b/public/language/de/admin/manage/user-custom-fields.json @@ -12,17 +12,17 @@ "input-type-text": "Eingabe (Text)", "input-type-link": "Eingabe (Link)", "input-type-number": "Eingabe (Zahl)", - "input-type-date": "Input (Date)", + "input-type-date": "Eingabe (Datum)", "input-type-select": "Auswählen", - "input-type-select-multi": "Select Multiple", + "input-type-select-multi": "Mehrere auswählen", "select-options": "Optionen", - "select-options-help": "Add one option per line for the select element", + "select-options-help": "Füge pro Zeile eine Option für das Auswahlelement hinzu.", "minimum-reputation": "Minimales Ansehen", - "minimum-reputation-help": "If a user has less than this value they won't be able to use this field", - "delete-field-confirm-x": "Do you really want to delete custom field \"%1\"?", + "minimum-reputation-help": "Wenn jemand weniger als diesen Wert hat, kann er dieses Feld nicht benutzen.", + "delete-field-confirm-x": "Willst du das benutzerdefinierte Feld „%1“ wirklich löschen?", "custom-fields-saved": "Benutzerdefinierte Felder gespeichert", - "visibility": "Visibility", - "visibility-all": "Everyone can see the field", - "visibility-loggedin": "Only logged in users can see the field", - "visibility-privileged": "Only privileged users like admins & moderators can see the field" + "visibility": "Sichtbarkeit", + "visibility-all": "Jeder kann das Feld sehen.", + "visibility-loggedin": "Nur angemeldete Nutzer können das Feld sehen", + "visibility-privileged": "Nur Leute mit besonderen Rechten wie Admins und Moderatoren können das Feld sehen." } \ No newline at end of file diff --git a/public/language/de/admin/manage/users.json b/public/language/de/admin/manage/users.json index 4dc1ae4ad9..a3965798a8 100644 --- a/public/language/de/admin/manage/users.json +++ b/public/language/de/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 pro Seite", "500-per-page": "500 pro Seite", + "search.help": "Benutz "*" um nach Teilen von Wörtern zu suchen, zum Beispiel "*anfrage"", "search.uid": "Nach Benutzer-ID", "search.uid-placeholder": "Gib eine Benutzer-ID ein um danach zu suchen", "search.username": "Nach Nutzernamen", @@ -55,7 +56,7 @@ "inactive.12-months": "12 Monate", "users.uid": "UID", - "users.user-id": "User ID", + "users.user-id": "Benutzer-ID", "users.username": "Nutzername", "users.email": "E-Mail", "users.no-email": "(keine Email)", @@ -64,7 +65,7 @@ "users.validation-pending": "Bestätigung ausstehend", "users.validation-expired": "Bestätigung abgelaufen", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "Aktuelle IPs", "users.postcount": "Anzahl der Beiträge", "users.reputation": "Ansehen", "users.flags": "Meldungen", diff --git a/public/language/de/admin/menu.json b/public/language/de/admin/menu.json index 4c7ff4faa4..25a519adf7 100644 --- a/public/language/de/admin/menu.json +++ b/public/language/de/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "%1 Einstellungen", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", + "section-federation": "Föderation", + "federation/general": "Allgemein", + "federation/content": "Inhalt", + "federation/rules": "Kategorisierung", "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "federation/pruning": "Speicher", + "federation/safety": "Vertrauen & Sicherheit", "section-appearance": "Aussehen", "appearance/themes": "Themes", @@ -78,6 +78,7 @@ "advanced/logs": "Protokoll", "advanced/errors": "Fehler", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/de/admin/settings/activitypub.json b/public/language/de/admin/settings/activitypub.json index 1295262992..98ea96fe66 100644 --- a/public/language/de/admin/settings/activitypub.json +++ b/public/language/de/admin/settings/activitypub.json @@ -46,9 +46,10 @@ "server.filter-help-hostname": "Gib unten nur den Instanz-Hostnamen ein (z. B. example.org), jeweils durch Zeilenumbrüche getrennt.", "server.filter-allow-list": "Stattdessen als Allow-Liste verwenden", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "Ausgehend", + "content.summary-limit": "Anzahl der Zeichen, nach der eine Zusammenfassung erstellt wird", + "content.summary-limit-help": "Wenn Inhalte rausgeschickt werden, die diese Zeichenanzahl überschreiten, wird eine Zusammenfassung erstellt, die alle vollständigen Sätze vor dieser Grenze enthält. (Standard: 500)", + "content.break-string": "Notiz/Artikel-Trennzeichen", + "content.break-string-help": "\nDieses Trennzeichen kann von Power-Usern beim Erstellen neuer Themen manuell eingefügt werden. Es sagt NodeBB, dass der Inhalt bis zu dieser Stelle als Teil der Zusammenfassungverwendet werden soll. Wenn diese Zeichenfolge nicht benutzt wird, greift die Standardregel für die Zeichenanzahl. (Standard: [...])", + "content.world-default-cid": "Standard-Kategorie-ID für den "Welt" Seiten-Editor" } \ No newline at end of file diff --git a/public/language/de/admin/settings/email.json b/public/language/de/admin/settings/email.json index 94c0d8c5b9..22d478446d 100644 --- a/public/language/de/admin/settings/email.json +++ b/public/language/de/admin/settings/email.json @@ -13,10 +13,10 @@ "smtp-transport-help": "Du kannst aus einer Liste bekannter Email-Provider auswählen, oder einen benutzerdefinierten eingeben.", "smtp-transport.service": "Wähle einen Provider", "smtp-transport.service-custom": "Benutzerdefiniert...", - "smtp-transport.service-help": "Select a service name above in order to use the known information about it. Alternatively, select "Custom Service" and enter the details below.", - "smtp-transport.gmail-warning1": "If you are using GMail as your email provider, you will have to generate an "App Password" in order for NodeBB to authenticate successfully. You can generate one at the App Passwords page.", - "smtp-transport.gmail-warning2": "For more information about this workaround, please consult this NodeMailer article on the issue. An alternative would be to utilise a third-party emailer plugin such as SendGrid, Mailgun, etc. Browse available plugins here.", - "smtp-transport.auto-enable-toast": "It looks like you're configuring an SMTP transport. We enabled the \"SMTP Transport\" option for you.", + "smtp-transport.service-help": "Wähle oben einen Servicenamen aus, um die bekannten Informationen dazu zu verwenden. Alternativ wähle "Custom Service" aus und gib die Details unten ein.", + "smtp-transport.gmail-warning1": "Wenn GMail als E-Mail-Anbieter verwendet wird, muss ein "App Password" generiert werden, damit NodeBB die Authentifizierung erfolgreich durchführen kann. Du kannst ein solches Passwort auf der Seite App Passwords generieren.", + "smtp-transport.gmail-warning2": "Weitere Informationen zu dieser Problemumgehung findest du in diesem NodeMailer-Artikel zu diesem Thema. Eine Alternative wäre die Verwendung eines E-Mail-Plugins eines Drittanbieters wie SendGrid, Mailgun usw. Hier findest du eine Übersicht über die verfügbaren Plugins .", + "smtp-transport.auto-enable-toast": "Es sieht so aus, als würdest du einen SMTP-Transport konfigurieren. Wir haben die Option „SMTP-Transport” für dich aktiviert.", "smtp-transport.host": "SMTP Host", "smtp-transport.port": "SMTP Port", "smtp-transport.security": "Verbindungssicherheit", @@ -28,22 +28,22 @@ "smtp-transport.password": "Passwort", "smtp-transport.pool": "Gepoolte Verbindungen erlauben", "smtp-transport.pool-help": "Das Poolen von Verbindungen hindert NodeBB daran für jede neu erstellte E-Mail eine eigene Verbindung aufzubauen. Diese Option ist nur zutreffend, wenn SMTP aktiviert ist.", - "smtp-transport.allow-self-signed": "Allow self-signed certificates", - "smtp-transport.allow-self-signed-help": "Enabling this setting will allow you to use self-signed or invalid TLS certificates.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.allow-self-signed": "Akzeptiere selbst-signierte Zertifikate", + "smtp-transport.allow-self-signed-help": "Durch Aktivieren dieser Einstellung können selbstsignierte oder ungültige TLS-Zertifikate verwendet werden.", + "smtp-transport.test-success": "STMP Test-Email erfolgreich versendet.", "template": "E-Mail Vorlage bearbeiten", "template.select": "E-Mail Vorlage auswählen", "template.revert": "Original wiederherstellen", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "SMTP Einstellungen testen", "testing": "E-Mail Test", - "testing.success": "Test Email Sent.", + "testing.success": "Test-Email versendet", "testing.select": "E-Mail-Vorlage auswählen", "testing.send": "Test-E-Mail versenden", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" wird verwendet um Test Emails zu verschicken.", + "testing.send-help-smtp": "Der SMTP-Transport ist aktiviert und wird zum Versenden von E-Mails verwendet.", + "testing.send-help-no-plugin": "Es ist kein E-Mail-Plugin zum Versenden von E-Mails installiert, daher wird standardmäßig nodemailer verwendet.", + "testing.send-help": "Die Test-E-Mail wird unter Verwendung der auf dieser Seite gespeicherten Einstellungen an die E-Mail-Adresse des aktuell angemeldeten Benutzers gesendet.", "subscriptions": "Email Zusammenfassungen", "subscriptions.disable": "Deaktivierung der Email Zusammenfassungen", "subscriptions.hour": "Sende Zeit", diff --git a/public/language/de/admin/settings/general.json b/public/language/de/admin/settings/general.json index 4ea6834bda..4f6a5e7ef6 100644 --- a/public/language/de/admin/settings/general.json +++ b/public/language/de/admin/settings/general.json @@ -15,10 +15,10 @@ "title-layout": "Titel Layout", "title-layout-help": "Definiert wie der Browser Titel gebildet wird, z.B. {pageTitle} | {browserTitle}", "description.placeholder": "Eine kurze Beschreibung der Community", - "description": "Site Description", + "description": "Seitenbeschreibung", "keywords": "Forum Schlüsselworte", "keywords-placeholder": "Schlüsselworte, die ihre Community beschreiben, mit Komma getrennt", - "logo-and-icons": "Website-Logo & Icons", + "logo-and-icons": "Medien & Branding", "logo.image": "Bild", "logo.image-placeholder": "Pfad zu einem Logo, welches im Header des Forums angezeigt werden soll", "logo.upload": "Hochladen", @@ -35,6 +35,8 @@ "touch-icon.help": "Empfohlene Größe und Format: 512x512, nur PNG-Format. Wenn kein Touch-Symbol angegeben wird, verwendet NodeBB wieder das Favicon.", "maskable-icon": "Maskierbares (Start-Bildschirm) Symbol", "maskable-icon.help": "Empfohlene Größe und Format: 512x512, nur PNG-Format. Wenn kein maskierbares Icon angegeben wird, greift NodeBB auf das Touch-Symbol zurück.", + "screenshot": "Screenshot", + "screenshot.help": "Empfohlene Größe und Format: zwischen 320px und 3480px, nur JPG- und PNG-Format. Wenn kein Screenshot angegeben wird, greift NodeBB auf einen Standard-Screenshot zurück", "outgoing-links": "Ausgehende Links", "outgoing-links.warning-page": "Warnseite für ausgehende links verwenden", "search": "Suche", @@ -51,13 +53,13 @@ "topic-tools": "Themen-Tools", "home-page": "Startseite", "home-page-route": "Startseiten Route", - "home-page-description": "Choose what page is shown when users navigate to the root URL of your forum.", + "home-page-description": "Wähle aus, welche Seite angezeigt wird, wenn Benutzer zur Stamm-URL des Forums navigieren.", "custom-route": "Benutzerdefinierte Route", "allow-user-home-pages": "Benutzer-Startseiten zulassen", "home-page-title": "Titel der Startseite (Standardmäßig \"Home\")", "default-language": "Standardsprache", "auto-detect": "Sprach-Einstellung bei Gästen automatisch ermitteln", - "default-language-help": "Die Standardsprache bestimmt die Spracheinstellungen für alle Benutzer, die dein Forum besuchen.
Einzelne Benutzer können die Standardsprache auf ihrer Kontoeinstellungsseite überschreiben.", + "default-language-help": "Die Standardsprache bestimmt die Spracheinstellungen für alle Benutzer, die das Forum besuchen.
Einzelne Benutzer können die Standardsprache auf ihrer Kontoeinstellungsseite überschreiben.", "post-sharing": "Beitragsfreigabe", "info-plugins-additional": "Plugins können zusätzliche Netzwerke zum Teilen von Beiträgen hinzufügen." } \ No newline at end of file diff --git a/public/language/de/admin/settings/navigation.json b/public/language/de/admin/settings/navigation.json index fbbb4f5ca0..3de2f7a02a 100644 --- a/public/language/de/admin/settings/navigation.json +++ b/public/language/de/admin/settings/navigation.json @@ -10,7 +10,7 @@ "id": "ID: optional", "properties": "Eigenschaften:", - "show-to-groups": "Show to Groups:", + "show-to-groups": "In Gruppen anzeigen:", "open-new-window": "In neuem Fenster öffnen", "dropdown": "Dropdown", "dropdown-placeholder": "Platziere deine Dropdown-Menüpunkte unten, d. h.:
<li><a class="dropdown-item" href="https://myforum.com">Link 1</a></li>", diff --git a/public/language/de/admin/settings/notifications.json b/public/language/de/admin/settings/notifications.json index 578bb826fb..2c400b6c50 100644 --- a/public/language/de/admin/settings/notifications.json +++ b/public/language/de/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "Willkommens-Benachrichtigungslink", "welcome-notification-uid": "Begrüßungsbenachrichtigungsbenutzer (UID)", "post-queue-notification-uid": "Post-Queue-Benutzer (UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "Verzögerung beim Versenden von Benachrichtigungs-E-Mails (Sekunden)", + "notification-delay-help": "Wenn der Benutzer die Benachrichtigung innerhalb dieser Zeit gelesen hat, wird die E-Mail nicht gesendet.
Standard: 60 Sekunden." } \ No newline at end of file diff --git a/public/language/de/admin/settings/post.json b/public/language/de/admin/settings/post.json index d664fceac4..860a33a742 100644 --- a/public/language/de/admin/settings/post.json +++ b/public/language/de/admin/settings/post.json @@ -8,7 +8,7 @@ "sorting.recently-created": "Kürzlich erstellt", "sorting.most-votes": "Meiste Bewertungen", "sorting.most-posts": "Meiste Beiträge", - "sorting.most-views": "Most Views", + "sorting.most-views": "Meist Gesehen", "sorting.topic-default": "Standardmäßige Themensortierung", "length": "Beitragslänge", "post-queue": "Beitragswarteschlange", diff --git a/public/language/de/admin/settings/reputation.json b/public/language/de/admin/settings/reputation.json index 7a539a4e86..3c331733ba 100644 --- a/public/language/de/admin/settings/reputation.json +++ b/public/language/de/admin/settings/reputation.json @@ -2,14 +2,14 @@ "reputation": "Ansehenseinstellungen", "disable": "Ansehenssystem deaktivieren", "disable-down-voting": "Negative Bewertungen deaktivieren", - "upvote-visibility": "Up Vote visibility", - "upvote-visibility-all": "Everyone can see up votes", - "upvote-visibility-loggedin": "Only logged in users can see up votes", - "upvote-visibility-privileged": "Only privileged users like admins & moderators can see up votes", - "downvote-visibility": "Down Vote visibility", - "downvote-visibility-all": "Everyone can see down votes", - "downvote-visibility-loggedin": "Only logged in users can see down votes", - "downvote-visibility-privileged": "Only privileged users like admins & moderators can see down votes", + "upvote-visibility": "Sichtbarkeit von positiven Bewertungen", + "upvote-visibility-all": "Jeder kann die positiven Bewertungen sehen", + "upvote-visibility-loggedin": "Nur angemeldete Benutzer können positive Bewertungen sehen", + "upvote-visibility-privileged": "Nur privilegierte Benutzer wie Administratoren und Moderatoren können positive Bewertungen sehen", + "downvote-visibility": "Sichtbarkeit von negativen Bewertungen", + "downvote-visibility-all": "Jeder kann die negativen Bewertungen sehen", + "downvote-visibility-loggedin": "Nur angemeldete Benutzer können negative Bewertungen sehen", + "downvote-visibility-privileged": "Nur privilegierte Benutzer wie Administratoren und Moderatoren können negative Bewertungen sehen", "thresholds": "Aktivitätsschwelle", "min-rep-upvote": "Mindestreputation, um Beiträge hochzustimmen", "upvotes-per-day": "Upvotes pro Tag (für unbegrenzte Upvotes auf 0 setzen)", @@ -17,8 +17,8 @@ "min-rep-downvote": "Minimales Ansehen um Beiträge negativ zu bewerten", "downvotes-per-day": "Runtervoten pro Tag (auf 0 gesetzt für unbegrenzte Runtervotes)", "downvotes-per-user-per-day": "Runtervoten pro Benutzer pro Tag (auf 0 gesetzt für unbegrenzte Runtervotes)", - "min-rep-chat": "Mindestreputation zum Senden von Chatnachrichten", - "min-rep-post-links": "Mindestansehen, um Links zu posten", + "min-rep-chat": "Minimales Ansehen zum Senden von Chatnachrichten", + "min-rep-post-links": "Minimales Ansehen, um Links zu posten", "min-rep-flag": "Minimales Ansehen und Beiträge zu melden", "min-rep-aboutme": "Erforderliche Reputation um eine \"Über mich\"-Sektion zum Benutzerprofil hinzuzufügen", "min-rep-signature": "Erforderliche Reputation um eine \"Signatur\" zum Benutzerprofil hinzuzufügen", @@ -29,12 +29,12 @@ "flags.limit-per-target": "Maximale Häufigkeit, mit der etwas gemeldet werden kann", "flags.limit-per-target-placeholder": "Standardwert: 0", "flags.limit-per-target-help": "Wenn ein Beitrag oder ein Benutzer mehrfach gemeldet wird, wird jede zusätzliche Meldung als "Report" betrachtet und zur ursprünglichen Meldung hinzugezählt. Setzen Sie diese Option auf eine andere Zahl als Null, um die Anzahl der Meldungen, die ein Report erhalten kann, zu begrenzen.", - "flags.limit-post-flags-per-day": "Maximum number of times a user can flag posts in a day", - "flags.limit-post-flags-per-day-help": "Set to 0 to disable, (default: 10)", - "flags.limit-user-flags-per-day": "Maximum number of times a user can flag users in a day", - "flags.limit-user-flags-per-day-help": "Set to 0 to disable, (default: 10)", - "flags.auto-flag-on-downvote-threshold": "Number of downvotes to auto flag posts", - "flags.auto-flag-on-downvote-threshold-help": "Set to 0 to disable, (default: 0)", + "flags.limit-post-flags-per-day": "Maximale Anzahl an Markierungen, die ein Benutzer pro Tag vornehmen kann", + "flags.limit-post-flags-per-day-help": "Auf 0 setzen, um zu deaktivieren (Standard: 10)", + "flags.limit-user-flags-per-day": "Maximale Anzahl von Benutzern, die ein Benutzer pro Tag melden kann", + "flags.limit-user-flags-per-day-help": "Auf 0 setzen, um zu deaktivieren (Standard: 10)", + "flags.auto-flag-on-downvote-threshold": "Anzahl der negativen Bewertungen, um Beiträge automatisch zu markieren", + "flags.auto-flag-on-downvote-threshold-help": "Auf 0 setzen, um zu deaktivieren (Standard: 0)", "flags.auto-resolve-on-ban": "Automatisches Beenden aller Tickets eines Benutzers, wenn dieser gesperrt wird", "flags.action-on-resolve": "Führe Folgendes aus, wenn eine Flagge aufgelöst wird", "flags.action-on-reject": "Gehe folgendermaßen vor, wenn eine Flagge abgelehnt wird", diff --git a/public/language/de/admin/settings/uploads.json b/public/language/de/admin/settings/uploads.json index ff5ee8d317..a29a031abc 100644 --- a/public/language/de/admin/settings/uploads.json +++ b/public/language/de/admin/settings/uploads.json @@ -40,7 +40,7 @@ "default-avatar": "Benutzerdefinierter Standardavatar", "upload": "Hochladen", "profile-image-dimension": "Profilbild-Abmessungen", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(in Pixeln, Standard: 2000 Pixel)", "max-profile-image-size": "Maximale Profibild-Dateigröße", "max-profile-image-size-help": "(In Kibibytes, Standardmäßig 256 KiB)", "max-cover-image-size": "Maximale Deckbild-Dateigröße", diff --git a/public/language/de/admin/settings/user.json b/public/language/de/admin/settings/user.json index 633d8e3d6f..b237b2d745 100644 --- a/public/language/de/admin/settings/user.json +++ b/public/language/de/admin/settings/user.json @@ -64,7 +64,7 @@ "show-email": "Zeige E-Mail-Adresse", "show-fullname": "Zeige vollen Namen", "restrict-chat": "Erlaube nur Chatnachrichten von Benutzern denen ich folge", - "disable-incoming-chats": "Disable incoming chat messages", + "disable-incoming-chats": "Deaktiviere eingehende Chat Nachrichten", "outgoing-new-tab": "Öffne externe Links in einem neuen Tab", "topic-search": "Suchen innerhalb von Themen aktivieren", "update-url-with-post-index": " URL während Themen durchsuchen mit dem Beitragsindex aktivieren", diff --git a/public/language/de/admin/settings/web-crawler.json b/public/language/de/admin/settings/web-crawler.json index 3addf20d7c..65662afd65 100644 --- a/public/language/de/admin/settings/web-crawler.json +++ b/public/language/de/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "RSS Feeds deaktivieren", "disable-sitemap-xml": "sitemap.xml deaktivieren", "sitemap-topics": "Anzahl der Themen, die in der Sitemap angezeigt werden sollen", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "Sitemap Cache Dauer (Stunden)", "clear-sitemap-cache": "Sitemap Cache leeren", "view-sitemap": "Sitemap anzeigen" } \ No newline at end of file diff --git a/public/language/de/aria.json b/public/language/de/aria.json index a33c879516..d32c04ea2b 100644 --- a/public/language/de/aria.json +++ b/public/language/de/aria.json @@ -1,10 +1,10 @@ { - "post-sort-option": "Post sort option, %1", - "topic-sort-option": "Topic sort option, %1", + "post-sort-option": "Option zum Sortieren von Beiträgen, %1", + "topic-sort-option": "Option zum Sortieren von Themen, %1", "user-avatar-for": "Benutzeravatar für %1", - "profile-page-for": "Profile page for user %1", - "user-watched-tags": "User watched tags", - "delete-upload-button": "Delete upload button", - "group-page-link-for": "Group page link for %1", - "show-crossposts": "Show Cross-posts" + "profile-page-for": "Profilseite für den Nutzer %1", + "user-watched-tags": "Vom Nutzer angesehene Tags", + "delete-upload-button": "Upload Button löschen", + "group-page-link-for": "Link zur Gruppenseite für %1", + "show-crossposts": "Cross-Posts anzeigen" } \ No newline at end of file diff --git a/public/language/de/category.json b/public/language/de/category.json index 7cac3f3368..debf9492a1 100644 --- a/public/language/de/category.json +++ b/public/language/de/category.json @@ -1,13 +1,13 @@ { "category": "Kategorie", "subcategories": "Unterkategorien", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", - "handle.description": "This category can be followed from the open social web via the handle %1", + "uncategorized": "Welt", + "uncategorized.description": "Themen außerhalb dieses Forums. Die hier vertretenen Ansichten und Meinungen spiegeln möglicherweise nicht die dieses Forums und seiner Mitglieder wider.", + "handle.description": "Diese Kategorie kann über das offene soziale Web unter dem Handle %1 verfolgt werden.", "new-topic-button": "Neues Thema", "guest-login-post": "Melde dich an, um einen Beitrag zu erstellen", "no-topics": "Es gibt noch keine Themen in dieser Kategorie.
Warum beginnst du nicht eins?", - "no-followers": "Nobody on this website is tracking or watching this category. Track or watch this category in order to begin receiving updates.", + "no-followers": "Niemand auf dieser Website verfolgt oder beobachtet diese Kategorie. Verfolgen oder beobachte diese Kategorie, um Updates zu erhalten.", "browsing": "Aktiv", "no-replies": "Niemand hat geantwortet", "no-new-posts": "Keine neuen Beiträge.", diff --git a/public/language/de/email.json b/public/language/de/email.json index 348383fe42..3300942257 100644 --- a/public/language/de/email.json +++ b/public/language/de/email.json @@ -3,8 +3,8 @@ "password-reset-requested": "Zurücksetzung des Passworts beantragt!", "welcome-to": "Willkommen bei %1", "invite": "Einladung von %1", - "greeting-no-name": "Hallo", - "greeting-with-name": "Hallo %1", + "greeting-no-name": "Hey", + "greeting-with-name": "Hey %1", "email.verify-your-email.subject": "Bitte bestätige deine Email-Adresse", "email.verify.text1": "Sie haben angefordert, dass wir Ihre E-Mail-Adresse ändern oder bestätigen", "email.verify.text2": "Aus Sicherheitsgründen ändern oder bestätigen wir die hinterlegte E-Mail-Adresse erst, nachdem ihr Eigentum per E-Mail bestätigt wurde. Wenn Sie dies nicht angefordert haben, müssen Sie nichts unternehmen.", diff --git a/public/language/de/error.json b/public/language/de/error.json index 1d125a1d9f..c7e7fcf4eb 100644 --- a/public/language/de/error.json +++ b/public/language/de/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ungültige Daten", + "invalid-config-field-value": "Der Wert für das Konfigurationsfeld „%1“ ist nicht okay: %2", "invalid-json": "Ungültiges JSON", "wrong-parameter-type": "Für die Eigenschaft „%1“ wurde ein Wert vom Typ %3 erwartet, aber stattdessen wurde %2 empfangen", "required-parameters-missing": "Bei diesem API-Aufruf fehlten erforderliche Parameter: %1", @@ -32,7 +33,7 @@ "invalid-path": "Ungültiger Pfad", "folder-exists": "Ordner existiert", "invalid-pagination-value": "Ungültige Seitennummerierung, muss mindestens %1 und maximal %2 sein", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "Ungültiger Wert für ungelesene Nachrichten, muss mindestens 1 und höchstens %1 sein", "username-taken": "Der Benutzername ist bereits vergeben", "email-taken": "Die E-Mail-Adresse ist bereits vergeben.", "email-nochange": "Die eingegebene E-Mail ist die gleiche wie die bereits hinterlegte E-Mail.", diff --git a/public/language/de/flags.json b/public/language/de/flags.json index f158d09604..a2889ecee7 100644 --- a/public/language/de/flags.json +++ b/public/language/de/flags.json @@ -1,27 +1,27 @@ { "state": "Zustand", - "report": "Report", - "reports": "Reports", + "report": "Meldung", + "reports": "Meldungen", "first-reported": "Zuerst gemeldet", - "no-flags": "Hurra! Keine Meldungen gefunden.", - "x-flags-found": "%1 Meldung(en) gefunden.", + "no-flags": "Hurra! Keine Markierungen gefunden.", + "x-flags-found": "%1 Markierung(en) gefunden.", "assignee": "Zugeordneter Benutzer", "update": "Aktualisieren", "updated": "Aktualisiert", "resolved": "Gelöst", "report-added": "Hinzugefügt", "report-rescinded": "Zurückgezogen", - "target-purged": "Der Inhalt auf den diese Meldung hingewiesen hat, wurde gelöscht und ist nicht mehr verfügbar.", + "target-purged": "Der Inhalt auf den diese Markierung hingewiesen hat, wurde gelöscht und ist nicht mehr verfügbar.", "target-aboutme-empty": "Dieser Benutzer hat kein \"Über mich\" gesetzt.", - "graph-label": "Tägliche Meldungen", + "graph-label": "Tägliche Markierungen", "quick-filters": "Schnell-Filter", - "filter-active": "Ein oder mehrere Filter sind in dieser Meldungs-Liste aktiv", + "filter-active": "Ein oder mehrere Filter sind in dieser Markierungs-Liste aktiv", "filter-reset": "Filter Entfernen", "filters": "Filter Optionen", "filter-reporterId": "Meldender", "filter-targetUid": "Gemeldeter", - "filter-type": "Meldungstyp", + "filter-type": "Markierungstyp", "filter-type-all": "Gesamter Inhalt", "filter-type-post": "Beitrag", "filter-type-user": "Benutzer", @@ -35,7 +35,7 @@ "fewer-filters": "weniger Filter", "quick-actions": "Schnellaktionen", - "flagged-user": "Gemeldeter Benutzer", + "flagged-user": "Markierter Benutzer", "view-profile": "Profil ansehen", "start-new-chat": "Neuen Chat beginnen", "go-to-target": "Meldungsziel ansehen", @@ -43,23 +43,23 @@ "delete-post": "Post löschen", "purge-post": "Post bereiningen", "restore-post": "Post wiederherstellen", - "delete": "Meldung löschen", + "delete": "Markierung löschen", "user-view": "Profil ansehen", "user-edit": "Profil bearbeiten", - "notes": "Meldungsnotizen", + "notes": "Markierungsnotizen", "add-note": "Notiz hinzufügen", "edit-note": "Notiz bearbeiten", "no-notes": "Keine geteilten Notizen", - "delete-note-confirm": "Bist du sicher, dass du diese Notiz löschen möchtest?", - "delete-flag-confirm": "Bist du dir sicher, dass du diese Meldung löschen möchtest?", + "delete-note-confirm": "Bist du sicher, dass du diese Markierungs-Notiz löschen möchtest?", + "delete-flag-confirm": "Bist du dir sicher, dass du diese Markierung löschen möchtest?", "note-added": "Notiz hinzugefügt", "note-deleted": "Notiz gelöscht", - "flag-deleted": "Meldung gelöscht", + "flag-deleted": "Markierung gelöscht", "history": "Konto & Markierungsverlauf", - "no-history": "Kein Meldungsverlauf", + "no-history": "Kein Markierungsverlauf", "state-all": "Alle Status", "state-open": "Neu/Öffnen", @@ -72,30 +72,30 @@ "sort-newest": "Neuste zuerst", "sort-oldest": "Älteste zuerst", "sort-reports": "Meiste Meldungen", - "sort-all": "Alle Meldungstypen ...", + "sort-all": "Alle Markierungstypen ...", "sort-posts-only": "Nur Beiträge ...", "sort-downvotes": "Meiste negativen Bewertungen", "sort-upvotes": "Meiste positive Bewertungen", "sort-replies": "Meiste Antworten", "modal-title": "Inhalt melden", - "modal-body": "Bitte geben Sie den Grund an, weshalb Sie %1 %2 melden wollen. Alternativ können Sie einen der Schnell-Meldungs-Knöpfe verwenden, wenn anwendbar.", + "modal-body": "Bitte gebe den Grund an, weshalb du %1 %2 markieren willst. Alternativ kannst du einen der Schnell-Meldungs-Knöpfe verwenden, wenn anwendbar.", "modal-reason-spam": "Spam", "modal-reason-offensive": "Beleidigend", "modal-reason-other": "Anderer (unten Angegeben)", "modal-reason-custom": "Grund für die Meldung dieses Inhalts...", - "modal-notify-remote": "Forward this report to %1", + "modal-notify-remote": "Leite diese Meldung weiter an %1", "modal-submit": "Meldung abschicken", - "modal-submit-success": "Der Inhalt wurde gemeldet.", + "modal-submit-success": "Der Inhalt wurde zur Überprüfung markiert.", - "modal-confirm-rescind": "Rescind Report?", + "modal-confirm-rescind": "Meldung widerrufen?", "bulk-actions": "Massenaktionen", - "bulk-resolve": "Meldung(en) bereiningen", - "confirm-purge": "Are you sure you want to permanently delete these flags?", - "purge-cancelled": "Flag Purge Cancelled", - "bulk-purge": "Purge Flag(s)", + "bulk-resolve": "Markierung(en) bereiningen", + "confirm-purge": "Bist du sicher, dass du diese Markierungen dauerhaft löschen möchtest?", + "purge-cancelled": "Löschen der Markierungen abgebrochen", + "bulk-purge": "Lösche Markierung(en)", "bulk-success": "%1 Meldungen aktualisiert", - "flagged-timeago": "Flagged ", + "flagged-timeago": "Markiert ", "auto-flagged": "[Automatisch gemeldet] %1 Abwertungen erhalten." } \ No newline at end of file diff --git a/public/language/de/global.json b/public/language/de/global.json index 08eac70aa7..d29d857ee8 100644 --- a/public/language/de/global.json +++ b/public/language/de/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "Erlaubte Dateitypen sind %1", "unsaved-changes": "Es gibt ungespeicherte Änderungen. Bist du dir sicher, dass du die Seite verlassen willst?", "reconnecting-message": "Es scheint als hättest du die Verbindung zu %1 verloren, bitte warte während wir versuchen sie wieder aufzubauen.", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "Erfolgreich wieder mit %1 verbunden.", "play": "Play", "cookies.message": "Diese Website verwendet Cookies, um sicherzustellen, dass du die besten Erfahrungen auf unserer Website machst.", "cookies.accept": "Verstanden!", diff --git a/public/language/de/groups.json b/public/language/de/groups.json index 18c4a01585..9fd5957e41 100644 --- a/public/language/de/groups.json +++ b/public/language/de/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "Gruppe", "all-groups": "Alle Gruppen", "groups": "Gruppen", "members": "Mitglieder", - "x-members": "%1 member(s)", + "x-members": "%1 Mitglied(er)", "view-group": "Gruppe zeigen", "owner": "Gruppenbesitzer", "new-group": "Neue Gruppe erstellen", diff --git a/public/language/de/modules.json b/public/language/de/modules.json index 38d3f657e0..b6c8835c27 100644 --- a/public/language/de/modules.json +++ b/public/language/de/modules.json @@ -1,7 +1,7 @@ { "chat.room-id": "Raum %1", "chat.chatting-with": "Chatte mit", - "chat.placeholder": "Type chat message here, drag & drop images", + "chat.placeholder": "Gib hier deine Chat-Nachricht ein, zieh Bilder per Drag & Drop hinein", "chat.placeholder.mobile": "Chatnachricht eingeben", "chat.placeholder.message-room": "Nachricht #%1", "chat.scroll-up-alert": "Zur neuesten Nachricht gehen", @@ -48,7 +48,7 @@ "chat.add-user": "Benutzer hinzufügen", "chat.notification-settings": "Benachrichtigungseinstellungen", "chat.default-notification-setting": "Standardeinstellung für die Benachrichtigung", - "chat.join-leave-messages": "Join/Leave Messages", + "chat.join-leave-messages": "Beitritts-/Austrittsnachrichten", "chat.notification-setting-room-default": "Raum Standard", "chat.notification-setting-none": "Keine Benachrichtigungen", "chat.notification-setting-at-mention-only": "@nur Erwähnung", @@ -82,7 +82,7 @@ "composer.hide-preview": "Vorschau ausblenden", "composer.help": "Hilfe", "composer.user-said-in": "%1 sagte in %2:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [sagte](%2):", "composer.discard": "Bist du sicher, dass du diesen Beitrag verwerfen möchtest?", "composer.submit-and-lock": "Einreichen und Sperren", "composer.toggle-dropdown": "Menu aus-/einblenden", @@ -106,7 +106,7 @@ "composer.zen-mode": "Zen Modus", "composer.select-category": "Wähle eine Kategorie", "composer.textarea.placeholder": "Schreibe hier deinen Beitrag, füge Bilder mit Drag and Drop hinzu", - "composer.post-queue-alert": "Hallo👋!
Da du ein neuer Benutzer bist, wird dein Beitrag ausgeblendet, bis er von unserem Moderationsteam freigegeben wurde.", + "composer.post-queue-alert": "Hey👋!
Da du ein neuer Benutzer bist, wird dein Beitrag ausgeblendet, bis er von unserem Moderationsteam freigegeben wurde.", "composer.schedule-for": "Thema einplanen für", "composer.schedule-date": "Datum", "composer.schedule-time": "Zeit", @@ -116,8 +116,8 @@ "composer.discard-all-drafts": "Alle Entwürfe verwerfen", "composer.no-drafts": "Keine Entwürfe vorhanden", "composer.discard-draft-confirm": "Möchtest Du diesen Entwurf verwerfen?", - "composer.remote-pid-editing": "Editing a remote post", - "composer.remote-pid-content-immutable": "The content of remote posts cannot be edited. However, you are able change the topic title and tags.", + "composer.remote-pid-editing": "Einen Remote-Beitrag bearbeiten", + "composer.remote-pid-content-immutable": "Der Inhalt von Remote-Beiträgen kann nicht bearbeitet werden. Du kannst aber den Titel und die Tags des Themas ändern.", "bootbox.ok": "OK", "bootbox.cancel": "Abbrechen", "bootbox.confirm": "Bestätigen", diff --git a/public/language/de/notifications.json b/public/language/de/notifications.json index 5ddf66d70b..14ebf18398 100644 --- a/public/language/de/notifications.json +++ b/public/language/de/notifications.json @@ -65,7 +65,7 @@ "new-register-multiple": "Es erwarten %1 Registrierungsanfragen eine Überprüfung.", "flag-assigned-to-you": "Markierung %1 wurde Ihnen zugewiesen", "post-awaiting-review": "Beitrag noch nicht Überprüft", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "Thema wartet auf Überprüfung", "profile-exported": "%1 Profil exportiert, klicke zum downloaden", "posts-exported": "%1 Posts exportiert, klicke zum downloaden", "uploads-exported": "%1 Uploads exportiert, klicke zum downloaden", diff --git a/public/language/de/pages.json b/public/language/de/pages.json index efe3397bc5..26c7140931 100644 --- a/public/language/de/pages.json +++ b/public/language/de/pages.json @@ -36,7 +36,7 @@ "chat": "Chatte mit %1", "flags": "Meldungen", "flag-details": "%1 Details melden", - "world": "World", + "world": "Welt", "account/edit": "Bearbeite %1", "account/edit/password": "Bearbeite Passwort von \"%1\"", "account/edit/username": "Bearbeite Benutzernamen von \"%1\"", @@ -63,7 +63,7 @@ "account/blocks": "Für %1 geblockte Benutzer", "account/uploads": "Uploads von %1", "account/sessions": "Login-Sitzungen", - "account/shares": "Topics shared by %1", + "account/shares": "Themen, die von %1 geteilt wurden", "confirm": "E-Mail bestätigt", "maintenance.text": "%1 befindet sich derzeit in der Wartung.
Bitte komme später wieder.", "maintenance.messageIntro": "Zusätzlich hat der Administrator diese Nachricht hinterlassen:", diff --git a/public/language/de/post-queue.json b/public/language/de/post-queue.json index a5ba8448c4..735345e0de 100644 --- a/public/language/de/post-queue.json +++ b/public/language/de/post-queue.json @@ -39,5 +39,5 @@ "remove-selected-confirm": "Möchtest Du %1 ausgewählte Beiträge entfernen?", "bulk-accept-success": "%1 Beiträge akzeptiert", "bulk-reject-success": "%1 Beiträge abgelehnt", - "links-in-this-post": "Links in this post" + "links-in-this-post": "Links in diesem Beitrag" } \ No newline at end of file diff --git a/public/language/de/recent.json b/public/language/de/recent.json index 7a88617de7..4ff9d514f0 100644 --- a/public/language/de/recent.json +++ b/public/language/de/recent.json @@ -8,6 +8,6 @@ "no-recent-topics": "Es gibt keine aktuellen Themen.", "no-popular-topics": "Es gibt keine beliebten Themen.", "load-new-posts": "Neue Beiträge laden", - "uncategorized.title": "All known topics", - "uncategorized.intro": "This page shows a chronological listing of every topic that this forum has received.
The views and opinions expressed in the topics below are not moderated and may not represent the views and opinions of this website." + "uncategorized.title": "Alle bekannten Themen", + "uncategorized.intro": "Auf dieser Seite findest du eine Liste aller Themen, die in diesem Forum angesprochen wurden, in chronologischer Reihenfolge.
Die Ansichten und Meinungen in den unten aufgeführten Themen werden nicht moderiert und geben nicht unbedingt die Ansichten und Meinungen dieser Website wieder." } \ No newline at end of file diff --git a/public/language/de/social.json b/public/language/de/social.json index 1ae8106ef9..fb30bcbf4f 100644 --- a/public/language/de/social.json +++ b/public/language/de/social.json @@ -9,6 +9,6 @@ "continue-with-facebook": "Mit Facebook fortsetzen", "sign-in-with-linkedin": "Mit LinkedIn anmelden", "sign-up-with-linkedin": "Mit LinkedIn registrieren", - "sign-in-with-wordpress": "Sign in with WordPress", - "sign-up-with-wordpress": "Sign up with WordPress" + "sign-in-with-wordpress": "Mit WordPress anmelden", + "sign-up-with-wordpress": "Mit WordPress anmelden" } \ No newline at end of file diff --git a/public/language/de/tags.json b/public/language/de/tags.json index 9b84674194..7e98c1eb50 100644 --- a/public/language/de/tags.json +++ b/public/language/de/tags.json @@ -3,7 +3,7 @@ "no-tag-topics": "Es gibt keine Themen mit diesem Schlagwort.", "no-tags-found": "Keine Tags gefunden", "tags": "Schlagworte", - "enter-tags-here": "Enter tags, %1 - %2 characters.", + "enter-tags-here": "Tags hinzufügen, %1 - %2 Buchstaben.", "enter-tags-here-short": "Schlagworte eingeben...", "no-tags": "Es gibt noch keine Schlagworte.", "select-tags": "Schlagworte auswählen", diff --git a/public/language/de/themes/harmony.json b/public/language/de/themes/harmony.json index 9a9aa225b2..1cd6abc7d3 100644 --- a/public/language/de/themes/harmony.json +++ b/public/language/de/themes/harmony.json @@ -1,25 +1,25 @@ { "theme-name": "Harmony Theme", "skins": "Skins", - "light": "Light", - "dark": "Dark", + "light": "Hell", + "dark": "Dunkel", "collapse": "Einklappen", "expand": "Ausklappen", - "sidebar-toggle": "Sidebar Toggle", + "sidebar-toggle": "Seitenleiste umschalten", "login-register-to-search": "Anmelden oder registrieren, um zu suchen", "settings.title": "Theme-Einstellungen", "settings.enableQuickReply": "Schnelle Antworten aktivieren", - "settings.enableBreadcrumbs": "Show breadcrumbs in Category and Topic pages", - "settings.enableBreadcrumbs.why": "Breadcrumbs are visible in most pages for ease-of-navigation. The base design of the category and topic pages has alternative means to link back to parent pages, but the breadcrumb can be toggled off to reduce clutter.", + "settings.enableBreadcrumbs": "Brotkrumen auf Kategorie- und Themenseiten anzeigen", + "settings.enableBreadcrumbs.why": "Brotkrumen sind auf den meisten Seiten zu sehen, damit man sich leichter zurechtfindet. Das Basisdesign der Kategorie- und Themenseiten hat andere Möglichkeiten, um zu den übergeordneten Seiten zurückzukehren, aber die Brotkrumen kann man ausschalten, damit es übersichtlicher ist.", "settings.centerHeaderElements": "Header-Elemente zentrieren", "settings.mobileTopicTeasers": "Themen-Vorschau auf Mobilgeräten anzeigen", "settings.stickyToolbar": "Klebrige Toolbar", "settings.stickyToolbar.help": "Die Toolbar auf Themen- und Kategorieseiten bleibt oben an der Seite kleben", - "settings.topicSidebarTools": "Topic sidebar tools", - "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", - "settings.autohideBottombar": "Auto hide mobile navigation bar", - "settings.autohideBottombar.help": "The mobile bar will be hidden when the page is scrolled down", - "settings.topMobilebar": "Move the mobile navigation bar to the top", + "settings.topicSidebarTools": "Themen-Seitenleiste-Tools", + "settings.topicSidebarTools.help": "Mit dieser Option werden die Themen-Tools auf dem Desktop in die Seitenleiste verschoben.", + "settings.autohideBottombar": "Mobile Navigationsleiste automatisch ausblenden", + "settings.autohideBottombar.help": "Die mobile Leiste wird ausgeblendet, wenn du auf der Seite nach unten scrollst.", + "settings.topMobilebar": "Verschieb die mobile Navigationsleiste nach oben.", "settings.openSidebars": "Seitennavigation öffnen", "settings.chatModals": "Chatfenster aktivieren" } \ No newline at end of file diff --git a/public/language/de/topic.json b/public/language/de/topic.json index c4cc890697..ef4bb801a6 100644 --- a/public/language/de/topic.json +++ b/public/language/de/topic.json @@ -225,7 +225,7 @@ "no-more-next-post": "Du hast keine weiteren Beiträge zu diesem Thema", "open-composer": "Composer öffnen", "post-quick-reply": "Schnell antworten", - "post-quick-create": "Quick post", + "post-quick-create": "Schneller Beitrag", "navigator.index": "Beitrag %1 von %2", "navigator.unread": "%1 ungelesen", "upvote-post": "Beitrag positiv bewerten", @@ -235,7 +235,7 @@ "thumb-image": "Miniaturbild zum Thema", "announcers": "Geteilt", "announcers-x": "geteilte (1 %)", - "guest-cta.title": "Hello! It looks like you're interested in this conversation, but you don't have an account yet.", - "guest-cta.message": "Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.", - "guest-cta.closing": "With your input, this post could be even better 💗" + "guest-cta.title": "Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.", + "guest-cta.message": "Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.", + "guest-cta.closing": "Mit deinem Input könnte dieser Beitrag noch besser werden 💗" } \ No newline at end of file diff --git a/public/language/de/user.json b/public/language/de/user.json index 624f7dd1ea..66b51adb89 100644 --- a/public/language/de/user.json +++ b/public/language/de/user.json @@ -147,7 +147,7 @@ "upvote-notif-freq.logarithmic": "Bei 10, 100, 1000...", "upvote-notif-freq.disabled": "Deaktiviert", "notification-type-web": "Web", - "notification-type-email": "Email", + "notification-type-email": "E-Mail", "browsing": "Browsing", "unread.cutoff": "Ungelesene Nachrichten (maximal %1 Tage)", "unread.cutoff-help": "Themen werden als gelesen markiert, wenn sie innerhalb dieser Anzahl von Tagen nicht aktualisiert wurden.", diff --git a/public/language/de/users.json b/public/language/de/users.json index 2793cb50f9..35e2ca2a84 100644 --- a/public/language/de/users.json +++ b/public/language/de/users.json @@ -1,6 +1,6 @@ { "all-users": "Alle Benutzer", - "followed-users": "Followed Users", + "followed-users": "Gefolgte Nutzer", "latest-users": "Neuste Benutzer", "top-posters": "Meiste Beiträge", "most-reputation": "Höchstes Ansehen", diff --git a/public/language/de/world.json b/public/language/de/world.json index 33dec67049..ba57a0e92d 100644 --- a/public/language/de/world.json +++ b/public/language/de/world.json @@ -1,25 +1,29 @@ { - "name": "World", - "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", - "recent": "All", + "name": "Welt", + "latest": "Neueste", + "latest-local": "Neueste (Lokal)", + "latest-all": "Neueste (Alle)", + "popular-day": "Beliebt (Tag)", + "popular-week": "Beliebt (Woche)", + "popular-month": "Beliebt (Monat)", + "popular-year": "Beliebt (Jahr)", + "popular-alltime": "Beliebt (alle Zeiten)", + "recent": "Alle", "help": "Hilfe", - "help.title": "What is this page?", - "help.intro": "Welcome to your corner of the fediverse.", - "help.fediverse": "The \"fediverse\" is a network of interconnected applications and websites that all talk to one another and whose users can see each other. This forum is federated, and can interact with that social web (or \"fediverse\"). This page is your corner of the fediverse. It consists solely of topics created by — and shared from — users you follow.", - "help.build": "There might not be a lot of topics here to start; that's normal. You will start to see more content here over time when you start following other users.", - "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", - "help.next-generation": "This is the next generation of social media, start contributing today!", + "help.title": "Was ist das für eine Seite?", + "help.intro": "Hey, willkommen in deiner Ecke des Fediversums.", + "help.fediverse": "Das „Fediverse“ ist ein Netzwerk aus miteinander verbundenen Apps und Websites, die alle miteinander reden und deren Nutzer sich gegenseitig sehen können. Dieses Forum ist föderiert und kann mit diesem sozialen Web (oder „Fediverse“) interagieren. Diese Seite ist dein Bereich im Fediverse. Sie besteht nur aus Themen, die von Nutzern erstellt — und geteilt wurden — denen du folgst.", + "help.build": "Es gibt hier vielleicht noch nicht so viele Themen, aber das ist ganz normal. Mit der Zeit wirst du hier mehr Inhalte sehen, wenn du anderen Nutzern folgst.", + "help.federating": "Wenn Leute außerhalb dieses Forums anfangen, dirzu folgen, werden deine Beiträge auch in diesen Apps und auf diesen Websites angezeigt.", + "help.next-generation": "Das ist die nächste Generation der sozialen Medien, leg noch heute los!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "Eine Welt voller Inhalte, immer griffbereit…", + "onboard.what": "Betrachte das als deinen weltweiten Entdeckungs-Feed. Hier findest du interessante Diskussionen aus dem gesamten Internet und anderen Communities – alles an einem Ort.", + "onboard.why": "Du kannst sehen, was gerade im Trend liegt, am besten nutzt du diesen Feed, indem du ihn ganz nach deinen Wünschen gestaltest. Wenn du ein Konto erstellst, kannst du bestimmten Creators und Themen folgen, um den Ballast auszusortieren und nur das zu sehen, was dir wichtig ist.", + "onboard.how": "Bist du bereit, loszulegen? Erstelle ein Konto, um anderen zu folgen, Benachrichtigungen zu erhalten, wenn dir ein Mensch antwortet, und deine Lieblingsfunde zu speichern.", - "category-search": "Find a category..." + "category-search": "Such eine Kategorie...", + "see-more": "Mehr sehen", + "see-less": "Weniger sehen" } \ No newline at end of file diff --git a/public/language/el/admin/advanced/jobs.json b/public/language/el/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/el/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/el/admin/dashboard.json b/public/language/el/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/el/admin/dashboard.json +++ b/public/language/el/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/el/admin/manage/users.json b/public/language/el/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/el/admin/manage/users.json +++ b/public/language/el/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/el/admin/menu.json b/public/language/el/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/el/admin/menu.json +++ b/public/language/el/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/el/admin/settings/activitypub.json b/public/language/el/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/el/admin/settings/activitypub.json +++ b/public/language/el/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/el/admin/settings/general.json b/public/language/el/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/el/admin/settings/general.json +++ b/public/language/el/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/el/error.json b/public/language/el/error.json index fdb0f8d116..e05e0556b0 100644 --- a/public/language/el/error.json +++ b/public/language/el/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Άκυρα Δεδομένα", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/el/world.json b/public/language/el/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/el/world.json +++ b/public/language/el/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/en-GB/admin/advanced/jobs.json b/public/language/en-GB/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/en-GB/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/en-GB/admin/menu.json b/public/language/en-GB/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/en-GB/admin/menu.json +++ b/public/language/en-GB/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/en-GB/admin/settings/activitypub.json b/public/language/en-GB/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/en-GB/admin/settings/activitypub.json +++ b/public/language/en-GB/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/en-GB/admin/settings/general.json b/public/language/en-GB/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/en-GB/admin/settings/general.json +++ b/public/language/en-GB/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/en-GB/world.json b/public/language/en-GB/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/en-GB/world.json +++ b/public/language/en-GB/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/en-US/admin/advanced/jobs.json b/public/language/en-US/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/en-US/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/en-US/admin/dashboard.json b/public/language/en-US/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/en-US/admin/dashboard.json +++ b/public/language/en-US/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/en-US/admin/manage/users.json b/public/language/en-US/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/en-US/admin/manage/users.json +++ b/public/language/en-US/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/en-US/admin/menu.json b/public/language/en-US/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/en-US/admin/menu.json +++ b/public/language/en-US/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/en-US/admin/settings/activitypub.json b/public/language/en-US/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/en-US/admin/settings/activitypub.json +++ b/public/language/en-US/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/en-US/admin/settings/general.json b/public/language/en-US/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/en-US/admin/settings/general.json +++ b/public/language/en-US/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/en-US/error.json b/public/language/en-US/error.json index 10c9469a66..e2d479d164 100644 --- a/public/language/en-US/error.json +++ b/public/language/en-US/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Invalid Data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/en-US/world.json b/public/language/en-US/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/en-US/world.json +++ b/public/language/en-US/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/en-x-pirate/admin/advanced/jobs.json b/public/language/en-x-pirate/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/en-x-pirate/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/en-x-pirate/admin/dashboard.json b/public/language/en-x-pirate/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/en-x-pirate/admin/dashboard.json +++ b/public/language/en-x-pirate/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/en-x-pirate/admin/manage/users.json b/public/language/en-x-pirate/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/en-x-pirate/admin/manage/users.json +++ b/public/language/en-x-pirate/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/en-x-pirate/admin/menu.json b/public/language/en-x-pirate/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/en-x-pirate/admin/menu.json +++ b/public/language/en-x-pirate/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/en-x-pirate/admin/settings/activitypub.json b/public/language/en-x-pirate/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/en-x-pirate/admin/settings/activitypub.json +++ b/public/language/en-x-pirate/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/en-x-pirate/admin/settings/general.json b/public/language/en-x-pirate/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/en-x-pirate/admin/settings/general.json +++ b/public/language/en-x-pirate/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/en-x-pirate/error.json b/public/language/en-x-pirate/error.json index 10c9469a66..e2d479d164 100644 --- a/public/language/en-x-pirate/error.json +++ b/public/language/en-x-pirate/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Invalid Data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/en-x-pirate/world.json b/public/language/en-x-pirate/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/en-x-pirate/world.json +++ b/public/language/en-x-pirate/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/es/admin/advanced/jobs.json b/public/language/es/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/es/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/es/admin/dashboard.json b/public/language/es/admin/dashboard.json index 93e0990b6e..7e4133eb15 100644 --- a/public/language/es/admin/dashboard.json +++ b/public/language/es/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Temas", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Últimos 7 Días", "page-views-thirty": "Últimos 30 Días", "page-views-last-day": "Últimas 24 horas", - "page-views-custom": "Rango de Fechas Personalizado", + "page-views-custom": "Custom Range", "page-views-custom-start": "Inicio del rango", "page-views-custom-end": "Fin del rango", "page-views-custom-help": "Introduce un rango de fechas para las vistas de página que deseas ver. Si no hay ningún selector de fechas disponible, el formato aceptado es AAAA-MM-DD", diff --git a/public/language/es/admin/manage/users.json b/public/language/es/admin/manage/users.json index f45f85e7e0..02be2b2fbb 100644 --- a/public/language/es/admin/manage/users.json +++ b/public/language/es/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Por ID de Usuario", "search.uid-placeholder": "Introduce el ID del usuario a buscar", "search.username": "Por Nombre de Usuario", diff --git a/public/language/es/admin/menu.json b/public/language/es/admin/menu.json index 24c5a41254..74d7fb55e7 100644 --- a/public/language/es/admin/menu.json +++ b/public/language/es/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Registros", "advanced/errors": "Errores", "advanced/cache": "Caché", + "advanced/jobs": "Jobs", "development/logger": "Registro", "development/info": "Información", diff --git a/public/language/es/admin/settings/activitypub.json b/public/language/es/admin/settings/activitypub.json index 7dca33aad3..033001a12f 100644 --- a/public/language/es/admin/settings/activitypub.json +++ b/public/language/es/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/es/admin/settings/general.json b/public/language/es/admin/settings/general.json index 09a6c8295f..e76f554aae 100644 --- a/public/language/es/admin/settings/general.json +++ b/public/language/es/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Palabras Clave (keywords) del Sitio", "keywords-placeholder": "Palabras Clave (keywords) que describen tu comunidad, separadas por comas", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Imagen", "logo.image-placeholder": "Ruta al logo que se mostrará en la cabecera del foro", "logo.upload": "Subir", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Enlaces a sitios externos", "outgoing-links.warning-page": "Usar Página de Advertencia para Enlaces a Sitios Externos", "search": "Search", diff --git a/public/language/es/error.json b/public/language/es/error.json index eee7f7ee11..588063dc5c 100644 --- a/public/language/es/error.json +++ b/public/language/es/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Datos no válidos", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "JSON no válido", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/es/world.json b/public/language/es/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/es/world.json +++ b/public/language/es/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/et/admin/advanced/jobs.json b/public/language/et/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/et/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/et/admin/dashboard.json b/public/language/et/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/et/admin/dashboard.json +++ b/public/language/et/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/et/admin/manage/users.json b/public/language/et/admin/manage/users.json index 8bc487a46d..a6939010f6 100644 --- a/public/language/et/admin/manage/users.json +++ b/public/language/et/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "Kasutajanime järgi", diff --git a/public/language/et/admin/menu.json b/public/language/et/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/et/admin/menu.json +++ b/public/language/et/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/et/admin/settings/activitypub.json b/public/language/et/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/et/admin/settings/activitypub.json +++ b/public/language/et/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/et/admin/settings/general.json b/public/language/et/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/et/admin/settings/general.json +++ b/public/language/et/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/et/error.json b/public/language/et/error.json index 9b15f3984e..f98884ac0b 100644 --- a/public/language/et/error.json +++ b/public/language/et/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Vigased andmed", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/et/world.json b/public/language/et/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/et/world.json +++ b/public/language/et/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/fa-IR/admin/advanced/jobs.json b/public/language/fa-IR/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/fa-IR/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/fa-IR/admin/dashboard.json b/public/language/fa-IR/admin/dashboard.json index 683a5529f1..4cc367bab6 100644 --- a/public/language/fa-IR/admin/dashboard.json +++ b/public/language/fa-IR/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "موضوع‌ها", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "هفت روز آخر", "page-views-thirty": "۳۰ روز آخر", "page-views-last-day": "۲۴ ساعت آخر", - "page-views-custom": "محدوده‌ی تاریخ سفارشی", + "page-views-custom": "Custom Range", "page-views-custom-start": "شروع محدوده", "page-views-custom-end": "پایان محدوده", "page-views-custom-help": "محدوده تاریخی از بازدیدهای صفحه را که می خواهید مشاهده کنید وارد کنید. اگر انتخابگر تاریخ در دسترس نباشد، قالب پذیرفته شده YYYY-MM-DD است", diff --git a/public/language/fa-IR/admin/manage/users.json b/public/language/fa-IR/admin/manage/users.json index 42c2d5366d..b877bbf451 100644 --- a/public/language/fa-IR/admin/manage/users.json +++ b/public/language/fa-IR/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/fa-IR/admin/menu.json b/public/language/fa-IR/admin/menu.json index d966acae7f..addab5f4f1 100644 --- a/public/language/fa-IR/admin/menu.json +++ b/public/language/fa-IR/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "سیاهه ها", "advanced/errors": "Errors", "advanced/cache": "کش ", + "advanced/jobs": "Jobs", "development/logger": "سیاهه ساز", "development/info": "Info", diff --git a/public/language/fa-IR/admin/settings/activitypub.json b/public/language/fa-IR/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/fa-IR/admin/settings/activitypub.json +++ b/public/language/fa-IR/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/fa-IR/admin/settings/general.json b/public/language/fa-IR/admin/settings/general.json index e8b37f08e5..c401841a15 100644 --- a/public/language/fa-IR/admin/settings/general.json +++ b/public/language/fa-IR/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "جستجو", diff --git a/public/language/fa-IR/error.json b/public/language/fa-IR/error.json index 7f86d4c2d7..bde54a18fb 100644 --- a/public/language/fa-IR/error.json +++ b/public/language/fa-IR/error.json @@ -1,5 +1,6 @@ { "invalid-data": "داده(های) نامعتبر", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "JSON نامعتبر", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/fa-IR/world.json b/public/language/fa-IR/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/fa-IR/world.json +++ b/public/language/fa-IR/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/fi/admin/advanced/jobs.json b/public/language/fi/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/fi/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/fi/admin/dashboard.json b/public/language/fi/admin/dashboard.json index 2923cfe813..30c8bc509b 100644 --- a/public/language/fi/admin/dashboard.json +++ b/public/language/fi/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Aiheet", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Viimeiset 7 päivää", "page-views-thirty": "Viimeiset 30 päivää", "page-views-last-day": "Viimeiset 24 tuntia", - "page-views-custom": "Valitse oma aikaväli", + "page-views-custom": "Custom Range", "page-views-custom-start": "Aikavälin alkupiste", "page-views-custom-end": "Aikavälin loppupiste", "page-views-custom-help": "Syötä aikaväli, jonka ajalta haluat tarkastella kävijätietoja. Jos päivämääränvalitsinta ei ole saatavilla, oikea päivämäärämuoto on VVVV-KK-PP.", diff --git a/public/language/fi/admin/manage/users.json b/public/language/fi/admin/manage/users.json index 4fd0110a08..87c4ef3082 100644 --- a/public/language/fi/admin/manage/users.json +++ b/public/language/fi/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per sivulla", "500-per-page": "500 per sivulla", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Käyttäjän ID:llä", "search.uid-placeholder": "Syötä etsittävä käyttäjän ID", "search.username": "Käyttäjätunnuksella", diff --git a/public/language/fi/admin/menu.json b/public/language/fi/admin/menu.json index 9ec0f43b5d..828cb8ea34 100644 --- a/public/language/fi/admin/menu.json +++ b/public/language/fi/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/fi/admin/settings/activitypub.json b/public/language/fi/admin/settings/activitypub.json index c43363e641..678232c912 100644 --- a/public/language/fi/admin/settings/activitypub.json +++ b/public/language/fi/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/fi/admin/settings/general.json b/public/language/fi/admin/settings/general.json index 3f71acedf1..dc341d2e0c 100644 --- a/public/language/fi/admin/settings/general.json +++ b/public/language/fi/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Sivuston avainsanat", "keywords-placeholder": "Yhteisöäsi kuvaavat avainsanat pilkuin eroteltuina.", - "logo-and-icons": "Sivuston logo ja kuvakkeet", + "logo-and-icons": "Media & Branding", "logo.image": "Kuva", "logo.image-placeholder": "Foorumin otsakkeessa näytettävän logon sijainti.", "logo.upload": "Lataa", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Peitetttävä (aloitussivun) kuvake", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/fi/error.json b/public/language/fi/error.json index 488f6fc7b6..7f23cddcd0 100644 --- a/public/language/fi/error.json +++ b/public/language/fi/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Virheellinen data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/fi/world.json b/public/language/fi/world.json index 4fe18db0c4..d08b09de6f 100644 --- a/public/language/fi/world.json +++ b/public/language/fi/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/fr/admin/admin.json b/public/language/fr/admin/admin.json index 7a1e3d8e1d..6b4986f6f9 100644 --- a/public/language/fr/admin/admin.json +++ b/public/language/fr/admin/admin.json @@ -1,16 +1,16 @@ { - "alert.confirm-rebuild-and-restart": "Êtes-vous sûr de vouloir régénérer et redémarrer NodeBB ?", - "alert.confirm-restart": "Êtes-vous sûr de vouloir redémarrer NodeBB ?", + "alert.confirm-rebuild-and-restart": "Êtes-vous sûr de vouloir régénérer et redémarrer NodeBB ?", + "alert.confirm-restart": "Êtes-vous sûr de vouloir redémarrer NodeBB ?", - "acp-title": "%1 | Panneau d'administration NodeBB", + "acp-title": "%1 | Panneau d’administration NodeBB", "settings-header-contents": "Contenus", "changes-saved": "Modifications enregistrées", - "changes-saved-message": "Vos modifications de la configuration NodeBB ont été enregistrées.", - "changes-not-saved": "Modifications non enregistrées !", - "changes-not-saved-message": "NodeBB a rencontré un problème lors de l'enregistrement de vos modifications ! (%1)", + "changes-saved-message": "Vos modifications de configuration NodeBB ont été enregistrées.", + "changes-not-saved": "Modifications non enregistrées ", + "changes-not-saved-message": "NodeBB a rencontré un problème lors de l’enregistrement de vos modifications  (%1)", "save-changes": "Enregistrer les modifications", - "min": "Min :", - "max": "Max :", + "min": "Min :", + "max": "Max :", "view": "Voir", "edit": "Modifier", "add": "Ajouter", diff --git a/public/language/fr/admin/advanced/database.json b/public/language/fr/admin/advanced/database.json index d8ed6fc1b0..c8a1bbbbdb 100644 --- a/public/language/fr/admin/advanced/database.json +++ b/public/language/fr/admin/advanced/database.json @@ -1,9 +1,9 @@ { - "x-b": "%1 b", - "x-mb": "%1 Mb", - "x-gb": "%1 Gb", - "uptime-seconds": "Disponibilité en secondes", - "uptime-days": "Disponibilité en jours", + "x-b": "%1 B", + "x-mb": "%1 Mb", + "x-gb": "%1 Gb", + "uptime-seconds": "Disponibilité (secondes)", + "uptime-days": "Disponibilité (jours)", "mongo": "MongoDB", "mongo.version": "Version de MongoDB", @@ -13,27 +13,27 @@ "mongo.avg-object-size": "Taille moyenne des objets", "mongo.data-size": "Taille des données", "mongo.storage-size": "Taille du stockage", - "mongo.index-size": "Taille de l'index", - "mongo.file-size": "Taille de fichier", + "mongo.index-size": "Taille des index", + "mongo.file-size": "Taille des fichiers", "mongo.resident-memory": "Mémoire résidente", "mongo.virtual-memory": "Mémoire virtuelle", "mongo.mapped-memory": "Mémoire mappée", - "mongo.bytes-in": "Données entrées", - "mongo.bytes-out": "Données sorties", + "mongo.bytes-in": "Données entrantes", + "mongo.bytes-out": "Données sortantes", "mongo.num-requests": "Nombre de requêtes", "mongo.raw-info": "Informations brutes MongoDB", - "mongo.unauthorized": "NodeBB n'a pas pu interroger la base de données MongoDB pour obtenir des statistiques pertinentes. Assurez-vous que l'utilisateur utilisé par NodeBB contient le message \"clusterMonitor\" pour le rôle \"admin\" des bases de données.", + "mongo.unauthorized": "NodeBB n'a pas pu interroger MongoDB pour obtenir des statistiques. Assurez-vous que l'utilisateur utilisé par NodeBB possède le rôle "clusterMonitor" sur la base de données avec les droits "admin".", "redis": "Redis", "redis.version": "Version de Redis", "redis.keys": "Clés", - "redis.expires": "Expire", + "redis.expires": "Expiration", "redis.avg-ttl": "TTL moyen", "redis.connected-clients": "Clients connectés", "redis.connected-slaves": "Esclaves connectés", "redis.blocked-clients": "Clients bloqués", "redis.used-memory": "Mémoire utilisée", - "redis.memory-frag-ratio": "Ratio de fragmentation de la mémoire", + "redis.memory-frag-ratio": "Taux de fragmentation de la mémoire", "redis.total-connections-recieved": "Connexions totales reçues", "redis.total-commands-processed": "Commandes totales exécutées", "redis.iops": "Opérations instantanées par seconde", @@ -42,11 +42,11 @@ "redis.total-input": "Total des entrées", "redis.total-output": "Total des sorties", - "redis.keyspace-hits": "Keyspace Hits", - "redis.keyspace-misses": "Keyspace Misses", + "redis.keyspace-hits": "Succès du Keyspace", + "redis.keyspace-misses": "Échecs du Keyspace", "redis.raw-info": "Informations brutes Redis", - "postgres": "Postgres", - "postgres.version": "Version PostgreSQL", - "postgres.raw-info": "Info brute Postgres" + "postgres": "PostgreSQL", + "postgres.version": "Version de PostgreSQL", + "postgres.raw-info": "Informations brutes PostgreSQL" } diff --git a/public/language/fr/admin/advanced/errors.json b/public/language/fr/admin/advanced/errors.json index 6070619ca1..9c0f026d35 100644 --- a/public/language/fr/admin/advanced/errors.json +++ b/public/language/fr/admin/advanced/errors.json @@ -1,15 +1,15 @@ { "errors": "Erreurs", "figure-x": "Graphe %1", - "error-events-per-day": "Évènements %1 par jour", + "error-events-per-day": "Événements %1 par jour", "error.404": "404 non trouvé", "error.503": "503 Service indisponible", - "manage-error-log": "Gestion des journaux d'erreurs", - "export-error-log": "Exporter les journaux d'erreurs (CSV)", - "clear-error-log": "Effacer les journaux d'erreurs", + "manage-error-log": "Gestion des journaux d’erreurs", + "export-error-log": "Exporter les journaux d’erreurs (CSV)", + "clear-error-log": "Effacer les journaux d’erreurs", "route": "Chemin", "count": "Nombre", - "no-routes-not-found": "Hourra ! Aucune erreur 404 !", - "clear404-confirm": "Êtes-vous sûr de vouloir effacer les journaux d'erreurs 404 ?", - "clear404-success": "Erreurs \"404 non trouvé\" effacées" + "no-routes-not-found": "Hourra ! Aucune erreur 404 !", + "clear404-confirm": "Êtes-vous sûr de vouloir effacer les journaux d’erreurs 404 ?", + "clear404-success": "Erreurs « 404 not Found » effacées" } \ No newline at end of file diff --git a/public/language/fr/admin/advanced/jobs.json b/public/language/fr/admin/advanced/jobs.json new file mode 100644 index 0000000000..42a1e1f567 --- /dev/null +++ b/public/language/fr/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Tâches", + "job-name": "Nom de la tâche", + "schedule": "Planification", + "next-run": "Prochaine exécution", + "last-duration": "Durée précédente", + "running": "En cours", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/fr/admin/dashboard.json b/public/language/fr/admin/dashboard.json index 103aa9a94b..3c8605b416 100644 --- a/public/language/fr/admin/dashboard.json +++ b/public/language/fr/admin/dashboard.json @@ -6,16 +6,17 @@ "new-users": "Nouveaux utilisateurs", "posts": "Messages", "topics": "Sujets", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "Messages distants", + "remote-topics": "Sujets distants", + "messages": "Messages", "page-views-seven": "7 derniers jours", "page-views-thirty": "30 derniers jours", - "page-views-last-day": "Dernières 24 heures", - "page-views-custom": "Dates personnalisées", + "page-views-last-day": "Dernières 24 heures", + "page-views-custom": "Intervalle personnalisé", "page-views-custom-start": "Début", "page-views-custom-end": "Fin", - "page-views-custom-help": "Entrer une plage de date pour les vues que vous souhaitez afficher. Si aucun sélecteur de date n'est disponible, le format de date accepté est JJ-MM-AAAA.", - "page-views-custom-error": "Veuillez entrer une plage de date valide dans le format suivant : JJ-MM-AAAA", + "page-views-custom-help": "Entrez une plage de dates pour les vues que vous souhaitez afficher. Si aucun sélecteur de date n'est disponible, le format accepté est JJ-MM-AAAA.", + "page-views-custom-error": "Veuillez entrer une plage de dates valide au format JJ-MM-AAAA", "stats.yesterday": "Hier", "stats.today": "Aujourd'hui", @@ -27,29 +28,29 @@ "updates": "Mises à jour", "running-version": "NodeBB v%1 est actuellement installé.", - "keep-updated": "Assurez-vous que votre version de NodeBB est à jour pour les derniers patchs de sécurité et correctifs de bugs.", + "keep-updated": "Assurez-vous que votre version de NodeBB est à jour pour bénéficier des derniers correctifs de sécurité et de bugs.", "up-to-date": "Votre version est à jour ", - "upgrade-available": "

Une nouvelle version (v%1) est disponible. Veuillez mettre à jour NodeBB.

", + "upgrade-available": "Une nouvelle version (v%1) est disponible. Veuillez mettre à jour NodeBB.", "prerelease-upgrade-available": "Votre version est dépassée. Une nouvelle version (v%1) est disponible. Veuillez mettre à jour NodeBB.", - "prerelease-warning": "Ceci est une pré-version de NodeBB. Des bugs inattendus peuvent se produire. ", - "fallback-emailer-not-found": "E-mail de secours introuvable !", - "running-in-development": "Le forum est en mode développement. Il peut être sujet à certaines vulnérabilités, veuillez contacter votre administrateur système.", - "latest-lookup-failed": "Erreur de vérification de la dernière version disponible de NodeBB", + "prerelease-warning": "Ceci est une pré-version de NodeBB. Des bugs inattendus peuvent survenir. ", + "fallback-emailer-not-found": "E-mail de secours introuvable !", + "running-in-development": "Le forum est en mode développement et peut présenter certaines vulnérabilités. Veuillez contacter votre administrateur système.", + "latest-lookup-failed": "Échec de la vérification de la dernière version disponible de NodeBB", "notices": "Informations", "restart-not-required": "Pas de redémarrage nécessaire", "restart-required": "Redémarrage requis", "search-plugin-installed": "Le plugin de recherche est installé", "search-plugin-not-installed": "Le plugin de recherche n'est pas installé", - "search-plugin-tooltip": "Installer un plugin de recherche depuis la page des plugins pour activer la fonctionnalité de recherche", + "search-plugin-tooltip": "Installez un plugin de recherche depuis la page des plugins pour activer la fonctionnalité de recherche", - "control-panel": "Contrôle du système", - "rebuild-and-restart": "Régénérer & Redémarrer", + "control-panel": "Panneau de contrôle", + "rebuild-and-restart": "Régénérer & Redémarrer", "restart": "Redémarrer", - "restart-warning": "Régénérer ou redémarrer NodeBB coupera toutes les connexions existantes pendant quelques secondes. ", - "restart-disabled": "La régénération et le redémarrage de votre forum ont été désactivés car vous ne semblez pas les exécuter à l'aide du serveur approprié.", + "restart-warning": "Régénérer ou redémarrer NodeBB coupera toutes les connexions existantes pendant quelques secondes.", + "restart-disabled": "La régénération et le redémarrage ont été désactivés, car vous ne semblez pas utiliser le serveur approprié.", "maintenance-mode": "Mode maintenance", - "maintenance-mode-title": "Cliquer ici pour passer NodeBB en mode maintenance", + "maintenance-mode-title": "Cliquez ici pour activer le mode maintenance de NodeBB", "dark-mode": "Mode sombre", "realtime-chart-updates": "Mises à jour des graphiques en temps réel", @@ -59,14 +60,14 @@ "active-users.total": "Total", "active-users.connections": "Connexions", - "guest-registered-users": "Utilisateurs invités vs enregistrés", + "guest-registered-users": "Invités vs utilisateurs enregistrés", "guest": "Invités", "registered": "Enregistrés", "user-presence": "Présence des utilisateurs", "on-categories": "Sur la liste des catégories", - "reading-posts": "Lit des messages", - "browsing-topics": "Parcourt les sujets", + "reading-posts": "Lecture des messages", + "browsing-topics": "Parcours des sujets", "recent": "Récents", "unread": "Non lus", @@ -77,28 +78,28 @@ "graphs.page-views-registered": "Membres", "graphs.page-views-guest": "Invités", "graphs.page-views-bot": "Robots", - "graphs.page-views-ap": "Vues de la page ActivityPub", + "graphs.page-views-ap": "Vues ActivityPub", "graphs.unique-visitors": "Visiteurs uniques", "graphs.registered-users": "Utilisateurs enregistrés", "graphs.guest-users": "Utilisateurs invités", "last-restarted-by": "Redémarré par", "no-users-browsing": "Aucun utilisateur connecté", - "back-to-dashboard": "Retour au Tableau de bord", - "details.no-users": "Aucun utilisateur ne s'est joint dans la période sélectionnée", - "details.no-topics": "Aucun sujet n'a été publié dans la période sélectionnée", - "details.no-searches": "Aucune recherche n'a été effectuée dans la période sélectionnée", - "details.no-logins": "Aucune connexion n'a été enregistrée dans la période sélectionnée", - "details.logins-static": "NodeBB n'enregistre que les données de session pendant %1 jours, le tableau ci-dessous n'affichera donc que les dernières sessions actives", + "back-to-dashboard": "Retour au tableau de bord", + "details.no-users": "Aucun utilisateur ne s'est connecté durant la période sélectionnée", + "details.no-topics": "Aucun sujet publié durant la période sélectionnée", + "details.no-searches": "Aucune recherche effectuée durant la période sélectionnée", + "details.no-logins": "Aucune connexion enregistrée durant la période sélectionnée", + "details.logins-static": "NodeBB n'enregistre les sessions que pendant %1 jours, le tableau ci-dessous ne montre donc que les sessions actives récentes", "details.logins-login-time": "Heure de connexion", "start": "Début", "end": "Fin", "filter": "Filtre", "view-as-json": "Afficher en JSON", "expand-analytics": "Développer les statistiques", - "clear-search-history": "Effacer l'historique", - "clear-search-history-confirm": "Êtes-vous sûr de vouloir effacer tout l'historique de recherche ?", + "clear-search-history": "Effacer l’historique", + "clear-search-history-confirm": "Êtes-vous sûr de vouloir effacer tout l’historique de recherche ?", "search-term": "Terme", "search-count": "Nombre", - "view-all": "Voir tout" + "view-all": "Tout afficher" } diff --git a/public/language/fr/admin/development/info.json b/public/language/fr/admin/development/info.json index 471fa8ede5..e1409be665 100644 --- a/public/language/fr/admin/development/info.json +++ b/public/language/fr/admin/development/info.json @@ -8,18 +8,18 @@ "nodejs": "nodejs", "online": "en ligne", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "RSS/Heap utilisé", "system-memory": "Mémoire système", "used-memory-process": "Mémoire utilisée par processus", "used-memory-os": "Mémoire système utilisée", "total-memory-os": "Mémoire système totale", "load": "Charge du système", "cpu-usage": "Utilisation du processeur", - "uptime": "disponibilité", + "uptime": "Disponibilité", "registered": "Enregistré", "sockets": "Sockets", - "connection-count": "nombre de connexions", + "connection-count": "Nombre de connexions", "guests": "Invités", "info": "Info" diff --git a/public/language/fr/admin/extend/plugins.json b/public/language/fr/admin/extend/plugins.json index ee8e3b5083..60ff180934 100644 --- a/public/language/fr/admin/extend/plugins.json +++ b/public/language/fr/admin/extend/plugins.json @@ -14,11 +14,11 @@ "submit-anonymous-usage": "Autoriser l'envoi anonyme des données d'utilisation des plugins", "reorder-plugins": "Réordonner les plugins", "order-active": "Trier les plugins actifs", - "dev-interested": "Êtes-vous intéressés par l'écriture de plugins pour NodeBB ?", - "docs-info": "La documentation complète concernant l’écriture de plugin peut être trouvée sur lePortail de Documentation de NodeBB.", + "dev-interested": "Êtes-vous intéressé par le développement de plugins pour NodeBB ?", + "docs-info": "La documentation complète sur l’écriture de plugins se trouve sur le Portail de documentation de NodeBB.", - "order.description": "Certains plugins fonctionnent mieux lorsqu'ils sont initialisés avant/après d'autres plugins.", - "order.explanation": "Les plugins se chargent dans l'ordre spécifié, ici de haut en bas.", + "order.description": "Certains plugins fonctionnent mieux lorsqu'ils sont initialisés avant ou après d'autres plugins.", + "order.explanation": "Les plugins se chargent dans l'ordre spécifié, de haut en bas.", "plugin-item.themes": "Thèmes", "plugin-item.deactivate": "Désactiver", @@ -27,32 +27,32 @@ "plugin-item.uninstall": "Désinstaller", "plugin-item.settings": "Réglages", "plugin-item.installed": "Installé", - "plugin-item.latest": "Dernier", + "plugin-item.latest": "Dernière version", "plugin-item.upgrade": "Mettre à jour", "plugin-item.more-info": "Pour plus d'informations :", "plugin-item.unknown": "Inconnu", - "plugin-item.unknown-explanation": "L'état de ce plugin n'a pas pu être déterminé, possiblement à cause d'une erreur de configuration.", - "plugin-item.compatible": "Ce plugin fonctionne sur NodeBB %1", - "plugin-item.not-compatible": "Attention, ce plugin n'est pas compatible avec votre version de NodeBB, assurez-vous qu'il fonctionne avant de l'installer sur votre environnement de production.", + "plugin-item.unknown-explanation": "L'état de ce plugin n'a pas pu être déterminé, probablement à cause d'une erreur de configuration.", + "plugin-item.compatible": "Ce plugin est compatible avec NodeBB %1", + "plugin-item.not-compatible": "Attention : ce plugin n'est pas compatible avec votre version de NodeBB. Vérifiez sa compatibilité avant de l'installer en production.", "alert.enabled": "Plugin activé", "alert.disabled": "Plugin désactivé", "alert.upgraded": "Plugin mis à jour", "alert.installed": "Plugin installé", "alert.uninstalled": "Plugin désinstallé", - "alert.activate-success": "Veuillez régénérer et redémarrer votre NodeBB pour activer complètement ce plugin", - "alert.deactivate-success": "Plugin désactivé avec succès", - "alert.upgrade-success": "Veuillez régénérer et redémarrer votre NodeBB pour finaliser la mise à jour de ce plugin.", - "alert.install-success": "Plugin installé avec succès, veuillez maintenant l'activer.", + "alert.activate-success": "Veuillez régénérer et redémarrer NodeBB pour activer complètement ce plugin.", + "alert.deactivate-success": "Plugin désactivé avec succès.", + "alert.upgrade-success": "Veuillez régénérer et redémarrer NodeBB pour finaliser la mise à jour du plugin.", + "alert.install-success": "Plugin installé avec succès. Veuillez maintenant l'activer.", "alert.uninstall-success": "Le plugin a été désactivé et désinstallé avec succès.", - "alert.suggest-error": "

NodeBB n'a pas pu joindre le gestionnaire de paquets, procéder à l'installation de la dernière version ?

Le serveur a répondu (%1) : %2
", - "alert.package-manager-unreachable": "

NodeBB n'a pas pu joindre le gestionnaire de paquets, une mise à jour n'est pas suggérée pour le moment.

", - "alert.incompatible": "

Votre version de NodeBB (v%1) ne peut mettre à jour que vers la version v%2 de ce plugin. Veuillez mettre à jour NodeBB si vous souhaitez installer une version plus récente de ce plugin.

", - "alert.possibly-incompatible": "

Aucune information de compatibilité trouvée

Ce plugin n'a pas spécifié de version pour une installation sur votre version de NodeBB. Aucune compatibilité ne peut être garantie et ce plugin pourrait empêcher NodeBB de démarrer correctement.

Dans l'éventualité où NodeBB ne pourrait pas démarrer proprement :

$ ./nodebb reset plugin=\"%1\"

Voulez-vous continuer l'installation de ce plugin ?

", + "alert.suggest-error": "

NodeBB n'a pas pu joindre le gestionnaire de paquets. Voulez-vous installer la dernière version ?

Réponse du serveur (%1): %2
", + "alert.package-manager-unreachable": "

NodeBB n'a pas pu joindre le gestionnaire de paquets. Aucune mise à jour n'est suggérée pour le moment.

", + "alert.incompatible": "

Votre version de NodeBB (v%1) ne peut mettre à jour que vers la version v%2 de ce plugin. Veuillez mettre à jour NodeBB pour installer une version plus récente du plugin.

", + "alert.possibly-incompatible": "

Compatibilité non spécifiée

Ce plugin n'a pas indiqué de version compatible avec votre NodeBB. Son fonctionnement n’est pas garanti et il pourrait empêcher NodeBB de démarrer correctement.

Si NodeBB ne démarre pas correctement :

$ ./nodebb reset plugin=\"%1\"

Voulez-vous continuer l'installation de ce plugin ?

", "alert.reorder": "Réorganiser les plugins", - "alert.reorder-success": "Veuillez régénérer et redémarrer votre NodeBB pour finaliser le processus.", + "alert.reorder-success": "Veuillez régénérer et redémarrer NodeBB pour finaliser le processus.", - "license.title": "Information sur la licence du plugin", - "license.intro": "Le plugin %1 est sous licence %2. Veuillez lire et comprendre les termes de la licence avant d’activer ce plugin.", - "license.cta": "Voulez-vous poursuivre en activant ce plugin ?" + "license.title": "Informations sur la licence du plugin", + "license.intro": "Le plugin %1 est sous licence %2. Veuillez lire et comprendre les termes de la licence avant de l’activer.", + "license.cta": "Voulez-vous continuer et activer ce plugin ?" } diff --git a/public/language/fr/admin/extend/widgets.json b/public/language/fr/admin/extend/widgets.json index 8fdce5ac24..d160839f49 100644 --- a/public/language/fr/admin/extend/widgets.json +++ b/public/language/fr/admin/extend/widgets.json @@ -2,13 +2,13 @@ "widgets": "Widgets", "available": "Widgets disponibles", "explanation": "Sélectionner un widget depuis le menu puis glissez & déposez-le dans une zone template du widget à gauche.", - "none-installed": "Aucun widget trouvé ! Activez le plugin Widget Essentials dans le panneau de configuration des plugins.", + "none-installed": "Aucun widget trouvé ! Activez le plugin Widget Essentials dans le panneau de configuration des plugins.", "clone-from": "Cloner le widget", "containers.available": "Conteneurs disponibles", "containers.explanation": "Glisser et déposer sur n'importe quel widget", "containers.none": "Aucun", "container.well": "Well", - "container.jumbotron": "Jombotron", + "container.jumbotron": "Jumbotron", "container.card": "Carte", "container.card-header": "En-tête", "container.card-body": "Corps", diff --git a/public/language/fr/admin/manage/categories.json b/public/language/fr/admin/manage/categories.json index 914f0bc93d..da4b176daa 100644 --- a/public/language/fr/admin/manage/categories.json +++ b/public/language/fr/admin/manage/categories.json @@ -3,43 +3,43 @@ "add-category": "Ajouter une catégorie", "add-local-category": "Ajouter une catégorie interne", "add-remote-category": "Ajouter une catégorie distante", - "remove": "Enlever", + "remove": "Supprimer", "rename": "Renommer", - "jump-to": "Aller à...", + "jump-to": "Aller à…", "settings": "Paramètres de la catégorie", - "edit-category": "Modifier les catégories", + "edit-category": "Modifier la catégorie", "privileges": "Privilèges", "back-to-categories": "Retour aux catégories", - "id": "ID Catégorie", + "id": "ID de la catégorie", "name": "Nom de la catégorie", - "handle": "Gestionnaire de catégorie", - "handle.help": "L'identifiant de votre catégorie sert à représenter cette catégorie sur d'autres réseaux, comme un nom d'utilisateur. Cet identifiant ne doit pas correspondre à un nom d'utilisateur ou à un groupe d'utilisateurs existant.", + "handle": "Identifiant de la catégorie", + "handle.help": "L'identifiant représente cette catégorie sur d'autres réseaux, comme un nom d’utilisateur. Il ne doit pas correspondre à un nom d’utilisateur ou à un groupe existant.", "description": "Description de la catégorie", "topic-template": "Modèle de sujet", "topic-template.help": "Définissez un modèle pour les nouveaux sujets créés dans cette catégorie.", - "bg-color": "Couleur d'arrière plan", + "bg-color": "Couleur de fond", "text-color": "Couleur du texte", - "bg-image-size": "Taille de l'image d'arrière plan", + "bg-image-size": "Taille de l'image de fond", "custom-class": "Classe personnalisée", - "num-recent-replies": "# de réponses récentes", + "num-recent-replies": "Nombre de réponses récentes", "ext-link": "Lien externe", "subcategories-per-page": "Sous-catégories par page", "is-section": "Traiter cette catégorie comme une section", "post-queue": "File d'attente", - "tag-whitelist": "Liste blanche de mots clés", - "upload-image": "Envoyer une image", - "upload": "Envoi", - "delete-image": "Enlever", + "tag-whitelist": "Liste blanche de mots-clés", + "upload-image": "Téléverser une image", + "upload": "Téléverser", + "delete-image": "Supprimer", "category-image": "Image de la catégorie", "image-and-icon": "Image & Icône", "parent-category": "Catégorie parente", "optional-parent-category": "Catégorie parente (optionnel)", - "top-level": "Vers le haut", - "parent-category-none": "(Aucun)", - "copy-parent": "Copier Parent", + "top-level": "Au sommet", + "parent-category-none": "(Aucune)", + "copy-parent": "Copier parent", "copy-settings": "Copier les paramètres de", - "optional-clone-settings": "Copier les paramètres de la catégorie (optionnel)", - "clone-children": "Copier les catégories et les paramètres", + "optional-clone-settings": "Copier les paramètres d'une catégorie (optionnel)", + "clone-children": "Copier les sous-catégories et leurs paramètres", "purge": "Vider la catégorie", "enable": "Activer", @@ -50,48 +50,48 @@ "view-category": "Voir la catégorie", "set-order": "Définir l'ordre", - "set-order-help": "Configuration des catégories. Vous pouvez déplacer vos catégories dans l'ordre que vous le souhaitez. La commande minimum est de 1, ce qui place la catégorie au sommet.", + "set-order-help": "Vous pouvez déplacer les catégories dans l'ordre souhaité. La valeur minimale est 1, ce qui place la catégorie au sommet.", "select-category": "Sélectionner une catégorie", "set-parent-category": "Définir une catégorie parente", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "Ici, vous pouvez définir les privilèges d’accès pour différentes parties du site. Les droits peuvent être attribués à des utilisateurs spécifiques ou à des groupes.", "privileges.category-selector": "Configuration des privilèges pour", - "privileges.warning": "Note: Les paramètres de privilège prennent effet instantanément . Il n'est pas nécessaire de sauvegarder la catégorie après avoir ajusté ces paramètres.", - "privileges.section-viewing": "Afficher les privilèges", - "privileges.section-posting": "Privilège de message", - "privileges.section-moderation": "Privilèges de modération", + "privileges.warning": "Note : Les paramètres de privilège prennent effet immédiatement. Il n'est pas nécessaire de sauvegarder la catégorie après les avoir ajustés.", + "privileges.section-viewing": "Afficher", + "privileges.section-posting": "Publier", + "privileges.section-moderation": "Modération", "privileges.section-other": "Autres", "privileges.section-user": "Utilisateur", "privileges.search-user": "Ajouter un utilisateur", - "privileges.no-users": "Aucun privilège spécifique aux utilisateurs dans cette catégorie.", + "privileges.no-users": "Aucun privilège spécifique pour les utilisateurs dans cette catégorie.", "privileges.section-group": "Groupe", "privileges.group-private": "Ce groupe est privé", - "privileges.inheritance-exception": "Ce groupe n'hérite pas des privilèges du groupe d'utilisateurs enregistrés", - "privileges.banned-user-inheritance": "Les utilisateurs bannis héritent des privilèges du groupe d'utilisateurs bannis", + "privileges.inheritance-exception": "Ce groupe n'hérite pas des privilèges du groupe d’utilisateurs enregistrés", + "privileges.banned-user-inheritance": "Les utilisateurs bannis héritent des privilèges du groupe des utilisateurs bannis", "privileges.search-group": "Ajouter un groupe", - "privileges.copy-to-children": "Copier aux enfants", + "privileges.copy-to-children": "Copier aux sous-catégories", "privileges.copy-from-category": "Copier depuis une catégorie", "privileges.copy-privileges-to-all-categories": "Copier dans toutes les catégories", - "privileges.copy-group-privileges-to-children": "Copier les privilèges de ce groupe aux enfants de cette catégorie.", - "privileges.copy-group-privileges-to-all-categories": "Copier les privilèges de ce groupe dans toutes les catégories.", - "privileges.copy-group-privileges-from": "Copiez les privilèges de ce groupe à partir d'une autre catégorie.", - "privileges.inherit": "Si le groupe utilisateurs enregistrés bénéficie d'un privilège supplémentaire, tous les autres groupes recevront un privilège implicite, même s'ils ne sont pas explicitement définis. Ce privilège implicite vous est montré car tous les utilisateurs font partie du groupe utilisateurs enregistrés ainsi, les privilèges accordés aux autres groupes ne doivent pas nécessairement être explicitement accordés.", - "privileges.copy-success": "Privilèges copiés !", + "privileges.copy-group-privileges-to-children": "Copier les privilèges de ce groupe aux sous-catégories", + "privileges.copy-group-privileges-to-all-categories": "Copier les privilèges de ce groupe dans toutes les catégories", + "privileges.copy-group-privileges-from": "Copier les privilèges de ce groupe depuis une autre catégorie", + "privileges.inherit": "Si le groupe utilisateurs enregistrés bénéficie d'un privilège supplémentaire, tous les autres groupes recevront un privilège implicite, même s'ils ne sont pas explicitement définis. Ce privilège implicite est montré ici car tous les utilisateurs font partie du groupe utilisateurs enregistrés, donc les privilèges des autres groupes n'ont pas besoin d'être explicitement définis.", + "privileges.copy-success": "Privilèges copiés !", "analytics.back": "Revenir à la liste des catégories", "analytics.title": "Statistiques pour la catégorie \"%1\"", - "analytics.pageviews-hourly": "Image 1 - Pages vues par heure pour cette catégorie", - "analytics.pageviews-daily": "Image 2 - Pages vues par jour pour cette catégorie", - "analytics.topics-daily": "Image 3 - Sujets créés par jour dans catégorie", - "analytics.posts-daily": "Image 4 - Messages par jour postés dans cette catégorie", + "analytics.pageviews-hourly": "Image 1 – Pages vues par heure pour cette catégorie", + "analytics.pageviews-daily": "Image 2 – Pages vues par jour pour cette catégorie", + "analytics.topics-daily": "Image 3 – Sujets créés par jour dans cette catégorie", + "analytics.posts-daily": "Image 4 – Messages postés par jour dans cette catégorie", "federation.title": "Fédération pour la catégorie \"%1\"", - "federation.disabled": "La fédération est désactivée sur l'ensemble du site, les paramètres de fédération par catégorie sont donc actuellement indisponibles.", + "federation.disabled": "La fédération est désactivée sur l'ensemble du site. Les paramètres par catégorie sont donc indisponibles.", "federation.disabled-cta": "Configuration de la fédération →", - "federation.syncing-header": "Synchronization", - "federation.syncing-intro": "Une catégorie peut suivre un « acteur de groupe » via ActivityPub. Le contenu provenant des acteurs ci‑dessous sera automatiquement ajouté à cette catégorie.", - "federation.syncing-caveat": "Remarque : configurer la synchronisation ici crée une synchronisation unidirectionnelle. NodeBB s’abonne / suit l’acteur, mais l’inverse n’est pas garanti.", + "federation.syncing-header": "Synchronisation", + "federation.syncing-intro": "Une catégorie peut suivre un « acteur de groupe » via ActivityPub. Le contenu provenant de ces acteurs sera automatiquement ajouté à cette catégorie.", + "federation.syncing-caveat": "Remarque : la synchronisation ici est unidirectionnelle. NodeBB suit l’acteur, mais l’inverse n’est pas garanti.", "federation.syncing-none": "Aucun suivi pour cette catégorie pour le moment.", "federation.syncing-add": "Synchroniser avec…", "federation.syncing-actorUri": "Acteur", @@ -104,26 +104,26 @@ "federation.followers-autofill": "Remplissage automatique", "alert.created": "Créée", - "alert.create-success": "Catégorie créée avec succès !", - "alert.none-active": "Vous n'avez aucune catégorie active.", + "alert.create-success": "Catégorie créée avec succès !", + "alert.none-active": "Aucune catégorie active.", "alert.create": "Créer une catégorie", "alert.add": "Ajouter une catégorie", - "alert.add-help": "Vous pouvez ajouter des catégories distantes à la liste en indiquant leur identifiant. Note : tous les sujets publiés dans la catégorie distante ne seront visibles que si au moins un utilisateur local la suit.", + "alert.add-help": "Les catégories distantes peuvent être ajoutées à la liste des catégories en spécifiant leur identifiant.

Note — La catégorie distante peut ne pas afficher tous les sujets publiés, à moins qu'au moins un utilisateur local ne la suive ou ne s'y abonne.", "alert.rename": "Renommer une catégorie distante", "alert.rename-help": "Entrez un nouveau nom pour cette catégorie. Laissez vide pour revenir au nom original.", "alert.confirm-remove": "Supprimer cette catégorie ? Elle peut être réajoutée à tout moment.", - "alert.confirm-purge": "

Voulez-vous vraiment purger cette catégorie \"%1\" ?

Attentionc!Tous les sujets et messages dans cette catégorie vont être supprimés

Purger une catégorie va enlever tous les sujets et messages en supprimant la catégorie de la base de données. Si vous voulez seulement enlevez une catégorietemporairement, il faut plutôt \"désactiver\" la catégorie.", - "alert.purge-success": "Catégorie purgée !", - "alert.copy-success": "Paramètres copiés !", - "alert.set-parent-category": "Définir une catégorie parent", + "alert.confirm-purge": "

Voulez-vous vraiment purger cette catégorie \"%1\" ?

Attention ! Tous les sujets et messages seront supprimés!

Purger une catégorie supprimera tous les sujets et messages, et effacera la catégorie de la base de données. Si vous souhaitez retirer une catégorie temporairement, vous devriez plutôt désactiver la catégorie à la place.

", + "alert.purge-success": "Catégorie purgée !", + "alert.copy-success": "Paramètres copiés !", + "alert.set-parent-category": "Définir une catégorie parente", "alert.updated": "Catégories mises à jour", - "alert.updated-success": "L' ID de la catégorie %1 a été mis à jour avec succès", - "alert.upload-image": "Uploader une image de catégorie", + "alert.updated-success": "L'ID de la catégorie %1 a été mis à jour avec succès", + "alert.upload-image": "Téléverser une image de catégorie", "alert.find-user": "Trouver un utilisateur", - "alert.user-search": "Chercher un utilisateur ici...", + "alert.user-search": "Rechercher un utilisateur ici…", "alert.find-group": "Trouver un groupe", - "alert.group-search": "Chercher un groupe ici...", - "alert.not-enough-whitelisted-tags": "Vous devez ajouter plus de mots-clés dans votre liste blanche ! Le nombre minimal requis est inférieur à ceux de votre liste blanche.", + "alert.group-search": "Rechercher un groupe ici…", + "alert.not-enough-whitelisted-tags": "Vous devez ajouter plus de mots-clés à votre liste blanche ! Le nombre actuel est insuffisant.", "collapse-all": "Tout réduire", "expand-all": "Tout développer", "disable-on-create": "Désactiver lors de la création", diff --git a/public/language/fr/admin/manage/custom-reasons.json b/public/language/fr/admin/manage/custom-reasons.json index 90a2e620af..01c7cc9bad 100644 --- a/public/language/fr/admin/manage/custom-reasons.json +++ b/public/language/fr/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", + "title": "Gérer les raisons personnalisées", + "create-reason": "Créer une raison", + "edit-reason": "Modifier la raison", + "reasons-help": "Les raisons sont des explications prédéfinies utilisées lors du bannissement ou de la mise en sourdine d’utilisateurs, ou lors du rejet de messages dans la file d’attente de modération.", + "reason-title": "Titre", "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "reason-body": "Corps", + "reason-all": "Tout", + "reason-ban": "Bannir", + "reason-mute": "Mettre en sourdine", + "reason-post-queue": "File d'attente des messages", + "reason-type-help": "Le type d’action auquel cette raison s’applique. Si « Tous » est sélectionné, cette raison sera disponible pour tous les types d’actions.", + "custom-reasons-saved": "Raisons personnalisées enregistrées avec succès.", + "delete-reason-confirm-x": "Êtes-vous sûr de vouloir supprimer la raison personnalisée intitulée %1 ?" } \ No newline at end of file diff --git a/public/language/fr/admin/manage/privileges.json b/public/language/fr/admin/manage/privileges.json index 04d780fea3..ee8419f895 100644 --- a/public/language/fr/admin/manage/privileges.json +++ b/public/language/fr/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "Droits des sujets", "create-topics": "Créer des sujets", "reply-to-topics": "Répondre aux sujets", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "Sujets distants", "schedule-topics": "Planifier des sujets", "tag-topics": "Tag des sujets", "edit-posts": "Modifier les messages", diff --git a/public/language/fr/admin/manage/user-custom-fields.json b/public/language/fr/admin/manage/user-custom-fields.json index cd7ec8a52d..de2e92b70a 100644 --- a/public/language/fr/admin/manage/user-custom-fields.json +++ b/public/language/fr/admin/manage/user-custom-fields.json @@ -3,26 +3,26 @@ "create-field": "Créer un champ", "edit-field": "Editer un champ", "manage-custom-fields": "Gérer les champs personnalisés", - "type-of-input": "Type of input", - "key": "Key", - "name": "Name", - "icon": "Icon", + "type-of-input": "Type de saisie", + "key": "Clé", + "name": "Nom", + "icon": "Icône", "type": "Type", - "min-rep": "Minimum Reputation", - "input-type-text": "Input (Text)", - "input-type-link": "Input (Link)", - "input-type-number": "Input (Number)", - "input-type-date": "Input (Date)", - "input-type-select": "Select", - "input-type-select-multi": "Select Multiple", + "min-rep": "Réputation minimum", + "input-type-text": "Saisie (texte)", + "input-type-link": "Saisie (Lien)", + "input-type-number": "Saisie (Nombre)", + "input-type-date": "Saisie (Date)", + "input-type-select": "Sélection", + "input-type-select-multi": "Sélection multiple", "select-options": "Options", - "select-options-help": "Add one option per line for the select element", - "minimum-reputation": "Minimum reputation", - "minimum-reputation-help": "If a user has less than this value they won't be able to use this field", - "delete-field-confirm-x": "Do you really want to delete custom field \"%1\"?", - "custom-fields-saved": "Custom fields saved", - "visibility": "Visibility", - "visibility-all": "Everyone can see the field", - "visibility-loggedin": "Only logged in users can see the field", - "visibility-privileged": "Only privileged users like admins & moderators can see the field" + "select-options-help": "Ajoutez une option par ligne pour l'élément de sélection", + "minimum-reputation": "Réputation minimum", + "minimum-reputation-help": "Si un utilisateur a moins que cette valeur, il ne pourra pas utiliser ce champ", + "delete-field-confirm-x": "Voulez-vous vraiment supprimer le champ personnalisé \"%1\" ?", + "custom-fields-saved": "Champs personnalisés sauvegardés", + "visibility": "Visibilité", + "visibility-all": "Tout le monde peut voir le champ", + "visibility-loggedin": "Seuls les membres connectés peuvent voir le champ", + "visibility-privileged": "Seuls les membres avec privilèges comme les admins & les modérateurs peuvent voir le champ" } \ No newline at end of file diff --git a/public/language/fr/admin/manage/users.json b/public/language/fr/admin/manage/users.json index 999e442664..dc77c85495 100644 --- a/public/language/fr/admin/manage/users.json +++ b/public/language/fr/admin/manage/users.json @@ -12,15 +12,15 @@ "password-reset-email": "Envoyer un e-mail de réinitialisation du mot de passe", "force-password-reset": "Forcer la réinitialisation du mot de passe et déconnecter l'utilisateur", "ban": "Bannir", - "ban-users": "Bannir l'utilisateur", - "temp-ban": "Bannir l'utilisateur temporairement", - "unban": "Débannir l'utilisateur", + "ban-users": "Bannir l'utilisateur(s)", + "temp-ban": "Bannir l'utilisateur(s) temporairement", + "unban": "Débannir l'utilisateur(s)", "reset-lockout": "Supprimer le blocage", "reset-flags": "Supprimer les signalements", "delete": "Supprimer", "delete-users": "Supprimer Utilisateur(s)", - "delete-content": "Supprimer le contenu du compte", - "purge": "Supprimer le compte et le contenu", + "delete-content": "Supprimer les contenus de l'utilisateur(s)", + "purge": "Supprimer l'utilisateur(s) et son contenu", "download-csv": "Exporter en CSV", "custom-user-fields": "Champs utilisateur personnalisés", "custom-reasons": "Raisons personnalisées", @@ -40,6 +40,7 @@ "250-per-page": "250 par page", "500-per-page": "500 par page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Par ID", "search.uid-placeholder": "Rechercher avec l'ID", "search.username": "Par nom d'utilisateur", @@ -55,7 +56,7 @@ "inactive.12-months": "12 mois", "users.uid": "uid", - "users.user-id": "User ID", + "users.user-id": "ID utilisateur", "users.username": "nom d'utilisateur", "users.email": "e-mail", "users.no-email": "(pas d'e-mail)", @@ -64,7 +65,7 @@ "users.validation-pending": "Validation en attente", "users.validation-expired": "Validation expirée", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "IP récente(s)", "users.postcount": "nombre de sujets", "users.reputation": "réputation", "users.flags": "signalements", @@ -88,10 +89,10 @@ "alerts.confirm-ban": "Voulez-vous réellement bannir définitivement cet utilisateur ?", "alerts.confirm-ban-multi": "Voulez-vous réellement bannir définitivement ces utilisateurs ?", - "alerts.ban-success": "Utilisateur(s) banni(s)", + "alerts.ban-success": "Utilisateur(s) banni(s) !", "alerts.button-ban-x": "Bannir %1 utilisateur(s)", "alerts.unban-success": "Utilisateur(s) débanni(s) !", - "alerts.lockout-reset-success": "Blocage(s) supprimé(s)", + "alerts.lockout-reset-success": "Blocage(s) supprimé(s) !", "alerts.password-change-success": "Mot(s) de passe modifié(s) !", "alerts.flag-reset-success": "Signalement(s) réinitialisé(s) !", "alerts.no-remove-yourself-admin": "Vous ne pouvez pas vous retirer vous-même des administrateurs !", @@ -104,17 +105,17 @@ "alerts.make-moderator-success": "L'utilisateur est maintenant modérateur.", "alerts.confirm-remove-moderator": "Voulez-vous vraiment supprimer ce modérateur ?", "alerts.remove-moderator-success": "L'utilisateur n'est plus modérateur.", - "alerts.confirm-validate-email": "Voulez-vous réellement valider les adresses e-mails de ces utilisateurs ?", + "alerts.confirm-validate-email": "Voulez-vous réellement valider les adresses e-mails de cet (ces) utilisateur(s) ?", "alerts.confirm-force-password-reset": "Êtes-vous sûr de vouloir forcer la réinitialisation du mot de passe et déconnecter cet (ces) utilisateur(s) ?", "alerts.validate-email-success": "Adresse e-mail validée", - "alerts.validate-force-password-reset-success": "Les mots de passe des utilisateurs ont été réinitialisés et leurs sessions existantes ont été révoquées.", - "alerts.password-reset-confirm": "Voulez-vous réellement envoyer un e-mail de réinitialisation de mot de passe à cet utilisateur ?", + "alerts.validate-force-password-reset-success": "Les mots de passe de cet (ces) utilisateurs ont été réinitialisés et leurs sessions existantes ont été révoquées.", + "alerts.password-reset-confirm": "Voulez-vous réellement envoyer un e-mail de réinitialisation de mot de passe à cet (ces) utilisateur(s) ?", "alerts.password-reset-email-sent": "Réinitialisation de mot de passe envoyée", - "alerts.confirm-delete": "Attention !

Voulez-vous réellement supprimer cet utilisateur ?

Cette action est irréversible ! Seul le compte sera supprimé, ses sujets et ses messages seront conservés

", - "alerts.delete-success": "Utilisateur supprimé !", - "alerts.confirm-delete-content": "Attention !

Voulez-vous réellement supprimer le contenu de cet utilisateur ?

Cette action est irréversible ! Toutes les données de cet utilisateur seront effacées !

", - "alerts.delete-content-success": "Contenu de l'utilisateur supprimé !", - "alerts.confirm-purge": "Attention !

Voulez-vous réellement supprimer cet utilisateur ainsi que son contenu ?

Cette action est irréversible ! Le compte de l'utilisateur ainsi que tout son contenu seront effacées !

", + "alerts.confirm-delete": "Attention !

Voulez-vous réellement supprimer cet (ces) utilisateur(s) ?

Cette action est irréversible ! Seul le compte sera supprimé, ses sujets et ses messages seront conservés

", + "alerts.delete-success": "Utilisateur(s) supprimé(s) !", + "alerts.confirm-delete-content": "Attention !

Voulez-vous réellement supprimer le contenu de cet (ces) utilisateur(s) ?

Cette action est irréversible ! Toutes les données de cet utilisateur seront effacées !

", + "alerts.delete-content-success": "Contenu de cet (ces) utilisateur(s) supprimé !", + "alerts.confirm-purge": "Attention !

Voulez-vous réellement supprimer cet (ces) utilisateur(s) ainsi que son contenu ?

Cette action est irréversible ! Le compte de l'utilisateur ainsi que tout son contenu seront effacées !

", "alerts.create": "Créer un utilisateur", "alerts.button-create": "Créer", "alerts.button-cancel": "Annuler", diff --git a/public/language/fr/admin/menu.json b/public/language/fr/admin/menu.json index 01724a9f37..644d423c78 100644 --- a/public/language/fr/admin/menu.json +++ b/public/language/fr/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "Réglages %1", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "Fédération", + "federation/general": "Général", + "federation/content": "Contenu", + "federation/rules": "Catégorisation", + "federation/relays": "Relais", + "federation/pruning": "Stockage", + "federation/safety": "Fiabilité et sécurité", "section-appearance": "Apparence", "appearance/themes": "Thèmes", @@ -78,6 +78,7 @@ "advanced/logs": "Journaux", "advanced/errors": "Erreurs", "advanced/cache": "Cache", + "advanced/jobs": "Tâches", "development/logger": "Réglages journalisation", "development/info": "Info", diff --git a/public/language/fr/admin/settings/activitypub.json b/public/language/fr/admin/settings/activitypub.json index eb1cbd4016..2fde051d4e 100644 --- a/public/language/fr/admin/settings/activitypub.json +++ b/public/language/fr/admin/settings/activitypub.json @@ -1,54 +1,55 @@ { - "intro-lead": "Qu'est-ce que la fédération ?", - "intro-body": "NodeBB est capable de communiquer avec d’autres instances de NodeBB qui le prennent en charge. Cela est réalisé via un protocole appelé ActivityPub. Si activé, NodeBB pourra également communiquer avec d’autres applications et sites web qui utilisent ActivityPub (par exemple Mastodon, Peertube, etc.)", + "intro-lead": "Qu’est-ce que la fédération ?", + "intro-body": "NodeBB peut communiquer avec d’autres instances NodeBB compatibles. Cela se fait via un protocole appelé ActivityPub. Si activé, NodeBB pourra également interagir avec d’autres applications et sites utilisant ActivityPub (par exemple Mastodon, Peertube, etc.)", "general": "Général", - "pruning": "Elagage de contenu", - "content-pruning": "Durée de conservatio du contenu distant", - "content-pruning-help": "Notez que le contenu distant qui a reçu une participation (une réponse ou un vote positif/négatif) sera préservé. (0 pour désactiver)", + "pruning": "Élagage du contenu", + "content-pruning": "Durée de conservation du contenu distant", + "content-pruning-help": "Notez que le contenu distant ayant reçu une interaction (réponse ou vote positif/négatif) sera conservé. (0 pour désactiver)", "user-pruning": "Durée de mise en cache des comptes utilisateurs distants", - "user-pruning-help": "Les comptes d’utilisateurs distants seront élagués s’ils n’ont pas de publications. Sinon, ils seront re-récupérés. (0 pour désactiver)", + "user-pruning-help": "Les comptes d’utilisateurs distants seront supprimés s’ils n’ont aucune publication. Sinon, ils seront récupérés à nouveau. (0 pour désactiver)", "enabled": "Activer la fédération", - "enabled-help": "Si activé, cela permettra à ce NodeBB de communiquer avec tous les clients compatibles ActivityPub sur le fediverse.", + "enabled-help": "Si activé, cette instance NodeBB pourra communiquer avec tous les clients compatibles ActivityPub sur le fediverse.", "allowLoopback": "Autoriser le traitement en boucle", - "allowLoopback-help": "Utile à des fins de débogage uniquement. Nous vous recommandons de laisser cela désactivé.", + "allowLoopback-help": "À utiliser uniquement à des fins de débogage. Il est recommandé de laisser cette option désactivée.", "probe": "Ouvrir dans l’application", - "probe-enabled": "Tenter d’ouvrir les ressources compatibles ActivityPub dans NodeBB", - "probe-enabled-help": "Si activé, NodeBB vérifiera chaque lien externe afin de déterminer s’il existe un équivalent ActivityPub, et le chargera dans NodeBB à la place.", - "probe-timeout": "Expiration de la recherche (ms)", - "probe-timeout-help": "(Par défaut : 2000) Si la requête de recherche n’obtient pas de réponse dans le délai défini, l’utilisateur est automatiquement redirigé vers le lien. Augmentez cette valeur si les sites répondent lentement et que vous souhaitez accorder davantage de temps.", + "probe-enabled": "Tenter d’ouvrir les ressources ActivityPub dans NodeBB", + "probe-enabled-help": "Si activé, NodeBB vérifiera chaque lien externe pour déterminer s’il existe un équivalent ActivityPub et l’affichera directement dans NodeBB.", + "probe-timeout": "Durée maximale de recherche (ms)", + "probe-timeout-help": "(Par défaut : 2000) Si la recherche n’obtient pas de réponse dans ce délai, l’utilisateur est automatiquement redirigé vers le lien. Augmentez cette valeur si les sites répondent lentement.", "rules": "Catégorisation", - "rules-intro": "Le contenu découvert via ActivityPub peut être automatiquement catégorisé en fonction de certaines règles (par exemple, hashtag)", - "rules.modal.title": "Comment cela fonctionne", - "rules.modal.instructions": "Tout contenu entrant est vérifié selon ces règles de catégorisation, et le contenu correspondant est automatiquement déplacé dans la catégorie de choix.

N.B. Le contenu qui est déjà catégorisé (c’est-à-dire dans une catégorie distante) ne passera pas par ces règles.", + "rules-intro": "Le contenu découvert via ActivityPub peut être automatiquement classé selon certaines règles (par exemple, hashtag).", + "rules.modal.title": "Comment ça fonctionne", + "rules.modal.instructions": "Tout contenu entrant est vérifié selon ces règles de catégorisation, et le contenu correspondant est automatiquement déplacé dans la catégorie choisie.

Remarque : Le contenu déjà catégorisé (c’est-à-dire dans une catégorie distante) n’est pas traité par ces règles.", "rules.add": "Ajouter une nouvelle règle", - "rules.help-hashtag": "Les sujets qui contiennent ce hashtag, quelle que soit la casse, seront inclus. Ne saisissez pas le symbole # ", - "rules.help-user": "Les sujets créés par l’utilisateur saisi seront pris en compte. Entrez un identifiant ou un ID complet (par ex. bob@exemple.org ou https://exemple.org/users/bob).", + "rules.help-hashtag": "Les sujets contenant ce hashtag, quelle que soit la casse, seront inclus. Ne saisissez pas le symbole #.", + "rules.help-user": "Les sujets créés par l’utilisateur spécifié seront pris en compte. Entrez un identifiant ou un ID complet (par ex. bob@exemple.org ou https://exemple.org/users/bob).", "rules.type": "Type", "rules.value": "Valeur", "rules.cid": "Catégorie", "relays": "Relais", - "relays.intro": "Un relais améliore la découverte de contenu vers et depuis votre instance NodeBB. S’abonner à un relais signifie que le contenu reçu par le relais est transmis ici, et que le contenu publié ici est diffusé vers l’extérieur par le relais.", - "relays.warning": "Remarque : les relais peuvent générer d’importants volumes de trafic entrant et entraîner une augmentation des coûts de stockage et de traitement.", - "relays.litepub": "NodeBB suit le standard de relais de type LitePub. L’URL que vous saisissez ici doit se terminer par /actor.", - "relays.add": "Ajouter un nouveau relais", + "relays.intro": "Un relais améliore la découverte de contenu vers et depuis votre instance NodeBB. S’abonner à un relais signifie que le contenu reçu par celui-ci est transmis ici, et que le contenu publié ici est diffusé vers l’extérieur par le relais.", + "relays.warning": "Attention : les relais peuvent générer un volume important de trafic entrant et augmenter les coûts de stockage et de traitement.", + "relays.litepub": "NodeBB suit le standard de relais LitePub. L’URL saisie doit se terminer par /actor.", + "relays.add": "Ajouter un relais", "relays.relay": "Relais", - "relays.state": "Etat", + "relays.state": "État", "relays.state-0": "En attente", - "relays.state-1": "Recevoir uniquement", + "relays.state-1": "Réception uniquement", "relays.state-2": "Actif", "server-filtering": "Filtrage", "count": "Ce NodeBB connaît actuellement %1 serveur(s)", - "server.filter-help": "Spécifiez les serveurs que vous souhaitez interdire de se fédérer avec votre NodeBB. Vous pouvez également autoriser sélectivement la fédération permettre avec certains serveurs. Ces deux options sont possibles, mais incompatibles.", - "server.filter-help-hostname": "Saisissez uniquement le nom d’hôte de l’instance ci-dessous (par ex. exemple.org), en les séparant par des sauts de ligne.", + "server.filter-help": "Spécifiez les serveurs que vous souhaitez interdire de se fédérer avec votre NodeBB. Vous pouvez également autoriser sélectivement la fédération avec certains serveurs. Ces deux options sont possibles, mais incompatibles.", + "server.filter-help-hostname": "Saisissez uniquement le nom d’hôte de l’instance (par ex. exemple.org), un par ligne.", "server.filter-allow-list": "Utiliser comme liste blanche", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "Sortant", + "content.summary-limit": "Nombre de caractères déclenchant la génération d’un résumé", + "content.summary-limit-help": "Lorsque le contenu fédéré dépasse ce nombre de caractères, un résumé est généré à partir de toutes les phrases complètes situées avant cette limite. (Par défaut : 500)", + "content.break-string": "Séparateur note/article", + "content.break-string-help": "Ce séparateur peut être inséré manuellement par les utilisateurs avancés lors de la création de nouveaux sujets. Il indique à NodeBB d’utiliser le contenu jusqu’à cet emplacement comme résumé. Si cette chaîne n’est pas utilisée, la limite de caractères par défaut s’applique. (Par défaut : [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/fr/admin/settings/email.json b/public/language/fr/admin/settings/email.json index 671d4447b7..6cd43cd678 100644 --- a/public/language/fr/admin/settings/email.json +++ b/public/language/fr/admin/settings/email.json @@ -28,22 +28,22 @@ "smtp-transport.password": "Mot de passe", "smtp-transport.pool": "Activer les connexions groupées", "smtp-transport.pool-help": "Le regroupement des connexions empêche NodeBB de créer une nouvelle connexion pour chaque e-mail. Cette option s'applique uniquement si le transport SMTP est activé.", - "smtp-transport.allow-self-signed": "Allow self-signed certificates", - "smtp-transport.allow-self-signed-help": "Enabling this setting will allow you to use self-signed or invalid TLS certificates.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.allow-self-signed": "Autoriser les certificats auto-signés", + "smtp-transport.allow-self-signed-help": "L’activation de ce paramètre vous permettra d’utiliser des certificats TLS auto-signés ou non valides.", + "smtp-transport.test-success": "L'e-mail de test SMTP a été envoyé avec succès.", "template": "Modifier le modèle d'e-mail", "template.select": "Sélectionner un modèle d'e-mail ", "template.revert": "Retourner à l'original", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "Tester les paramètres SMTP", "testing": "Test d'e-mail", - "testing.success": "Test Email Sent.", + "testing.success": "E-mail de test envoyé.", "testing.select": "Sélectionner un modèle d'e-mail ", "testing.send": "Envoyer un e-mail de test", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" sera utilisé pour envoyer les e-mails de test.", + "testing.send-help-smtp": "Le transport SMTP est activé et sera utilisé pour envoyer les e-mails.", + "testing.send-help-no-plugin": "Aucun plugin d'envoi d'e-mails n'est installé, nodemailer sera utilisé par défaut.", + "testing.send-help": "L'e-mail de test sera envoyé à l'adresse e-mail de l'utilisateur actuellement connecté en utilisant les paramètres enregistrés sur cette page.", "subscriptions": "Actualités du forum ", "subscriptions.disable": "Désactiver les actualités du forum ", "subscriptions.hour": "Heure d'envoi", diff --git a/public/language/fr/admin/settings/general.json b/public/language/fr/admin/settings/general.json index d4b6872288..2122df070a 100644 --- a/public/language/fr/admin/settings/general.json +++ b/public/language/fr/admin/settings/general.json @@ -15,10 +15,10 @@ "title-layout": "Disposition du titre", "title-layout-help": "Définir la manière dont le titre est structuré dans le navigateur ex : {pageTitle} | {browserTitle}", "description.placeholder": "Une courte description de votre communauté", - "description": "Site Description", + "description": "Description du site", "keywords": "Mots-clés du site", "keywords-placeholder": "Mots-clés décrivant votre communauté, séparés par des virgules", - "logo-and-icons": "Logo & Icônes du site", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Chemin vers un logo à afficher dans l'en-tête du forum", "logo.upload": "Téléverser", @@ -35,6 +35,8 @@ "touch-icon.help": "Taille et format recommandés : 512x512, format PNG uniquement. Si aucune icône d'accueil n'est spécifiée, le favicon NodeBB sera visible.", "maskable-icon": "Icône masquable (écran d'accueil)", "maskable-icon.help": "Taille et format recommandés : 512x512, format PNG uniquement. Si aucune icône masquable n'est spécifiée, le favicon NodeBB sera visible.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Liens sortants", "outgoing-links.warning-page": "Utiliser la page d'avertissement pour liens sortants", "search": "Rechercher", @@ -51,7 +53,7 @@ "topic-tools": "Outils pour les sujets", "home-page": "Page d'accueil", "home-page-route": "Route de la page d'accueil", - "home-page-description": "Choose what page is shown when users navigate to the root URL of your forum.", + "home-page-description": "Choisissez la page qui s'affiche lorsque les utilisateurs accèdent à l'URL racine de votre forum.", "custom-route": "Route personnalisée", "allow-user-home-pages": "Permettre aux utilisateurs de choisir une page d'accueil personnalisée", "home-page-title": "Titre de la page d'accueil (par défaut \"Accueil\")", diff --git a/public/language/fr/admin/settings/notifications.json b/public/language/fr/admin/settings/notifications.json index 31146324dc..20f00e46f2 100644 --- a/public/language/fr/admin/settings/notifications.json +++ b/public/language/fr/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "Lien de notification de bienvenue", "welcome-notification-uid": "Notification de bienvenue de l'utilisateur (UID)", "post-queue-notification-uid": "File d'attente utilisateur (UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "Délai d’envoi des e-mails de notification (secondes)", + "notification-delay-help": "Si l’utilisateur a lu la notification pendant ce délai, l’e-mail ne sera pas envoyé.
Valeur par défaut : 60 secondes." } \ No newline at end of file diff --git a/public/language/fr/admin/settings/uploads.json b/public/language/fr/admin/settings/uploads.json index ea8c68f769..c477949027 100644 --- a/public/language/fr/admin/settings/uploads.json +++ b/public/language/fr/admin/settings/uploads.json @@ -40,7 +40,7 @@ "default-avatar": "Modifier l'avatar par défaut", "upload": "Téléverser", "profile-image-dimension": "Dimensions de l'avatar", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(en pixels, par défaut : 200 pixels)", "max-profile-image-size": "Taille maximale des avatars", "max-profile-image-size-help": "(en kibioctets, défaut : 256 Kio)", "max-cover-image-size": "Taille maximale des images de couverture", diff --git a/public/language/fr/admin/settings/user.json b/public/language/fr/admin/settings/user.json index 57bb85c0ad..07f437f4fe 100644 --- a/public/language/fr/admin/settings/user.json +++ b/public/language/fr/admin/settings/user.json @@ -64,7 +64,7 @@ "show-email": "Afficher l'adresse e-mail", "show-fullname": "Afficher le nom complet", "restrict-chat": "Autoriser uniquement les discussions aux utilisateurs que je suis", - "disable-incoming-chats": "Disable incoming chat messages", + "disable-incoming-chats": "Désactiver la réception des messages de discussions", "outgoing-new-tab": "Ouvrir les liens sortants dans un nouvel onglet", "topic-search": "Activer la recherche au sein des sujets", "update-url-with-post-index": "Mettre à jour l'URL avec l'index des articles", diff --git a/public/language/fr/admin/settings/web-crawler.json b/public/language/fr/admin/settings/web-crawler.json index 2486ba4d9b..c22ee039a4 100644 --- a/public/language/fr/admin/settings/web-crawler.json +++ b/public/language/fr/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "Désactiver les flux RSS", "disable-sitemap-xml": "Désactiver le fichier sitemap.xml", "sitemap-topics": "Nombre de sujets à afficher dans le sitemap", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "Durée du cache du sitemap (heures)", "clear-sitemap-cache": "Effacer le cache du sitemap", "view-sitemap": "Afficher le sitemap" } \ No newline at end of file diff --git a/public/language/fr/aria.json b/public/language/fr/aria.json index e4b383b847..95e2b80968 100644 --- a/public/language/fr/aria.json +++ b/public/language/fr/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "L'utilisateur a regardé les tags", "delete-upload-button": "Supprimer le bouton de téléchargement", "group-page-link-for": "Lien vers la page de groupe pour %1", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "Afficher les messages imbriqués" } \ No newline at end of file diff --git a/public/language/fr/category.json b/public/language/fr/category.json index ec9effd39e..edebcf10ed 100644 --- a/public/language/fr/category.json +++ b/public/language/fr/category.json @@ -1,13 +1,13 @@ { "category": "Catégorie", "subcategories": "Sous-catégories", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", - "handle.description": "This category can be followed from the open social web via the handle %1", + "uncategorized": "Monde", + "uncategorized.description": "Sujets en dehors de ce forum. Les vues et opinions exprimées ici ne reflètent pas nécessairement celles de ce forum et de ses membres.", + "handle.description": "Cette catégorie peut être suivie depuis le web social ouvert via le pseudo %1", "new-topic-button": "Nouveau sujet", "guest-login-post": "Se connecter pour poster", "no-topics": "Il n'y a aucun sujet dans cette catégorie.
Pourquoi ne pas en créer un ?", - "no-followers": "Nobody on this website is tracking or watching this category. Track or watch this category in order to begin receiving updates.", + "no-followers": "Personne sur ce site n’a encore suivi ou surveillé cette catégorie. Suivez ou surveillez cette catégorie pour commencer à recevoir des mises à jour.", "browsing": "parcouru par", "no-replies": "Personne n'a répondu", "no-new-posts": "Pas de nouveau message", @@ -17,10 +17,10 @@ "tracking": "Suivi", "not-watching": "Ne plus suivre", "ignoring": "Ignoré", - "watching.description": "Me notifier les nouvelles réponses.
Afficher le sujet dans l'onglet \"Non lu\" et \"récent\"", - "tracking.description": "Afficher les sujets non lus et récents", - "not-watching.description": "Ne pas afficher les sujets non lus, afficher les récents", - "ignoring.description": "Ne pas afficher les sujets non lus et récents", + "watching.description": "Me notifier les nouvelles réponses.
Afficher le sujet dans les onglets \"Non lus\" et \"Récents\"", + "tracking.description": "Afficher les sujets \"Non lus\" et \"Récents\"", + "not-watching.description": "Ne pas afficher les sujets dans \"Non lus\", afficher dans \"Récents\"", + "ignoring.description": "Ne pas afficher les sujets dans \"Non lus\" et \"Récents\"", "watching.message": "Vous suivez maintenant les mises à jour de cette catégorie et de ses sous-catégories", "tracking.message": "Vous suivez maintenant les mises à jour de cette catégorie et de ses sous-catégories", "notwatching.message": "Vous ne suivez aucune mise à jour de cette catégorie et de ses sous-catégories.", diff --git a/public/language/fr/email.json b/public/language/fr/email.json index ca8884aaf8..8085c46e88 100644 --- a/public/language/fr/email.json +++ b/public/language/fr/email.json @@ -1,33 +1,33 @@ { - "test-email.subject": "Test e-mail", + "test-email.subject": "Test d’e-mail", "password-reset-requested": "Demande de réinitialisation de mot de passe !", "welcome-to": "Bienvenue sur %1", "invite": "Invitation de %1", "greeting-no-name": "Bonjour", "greeting-with-name": "Bonjour %1", "email.verify-your-email.subject": "Veuillez vérifier votre e-mail", - "email.verify.text1": "Vous avez demandé que nous modifions ou confirmions votre adresse mail", - "email.verify.text2": "Pour des raisons de sécurité, nous ne modifions ou ne confirmons l'adresse mail enregistrée que lorsque son propriétaire l'a confirmée. Si vous ne l'avez pas demandé, aucune action n'est requise de votre part.", + "email.verify.text1": "Vous avez demandé que nous modifiions ou confirmions votre adresse e-mail.", + "email.verify.text2": "Pour des raisons de sécurité, nous ne modifions ou ne confirmons l'adresse e-mail enregistrée que lorsque son propriétaire l'a confirmée. Si vous ne l'avez pas demandée, aucune action n'est requise de votre part.", "email.verify.text3": "Une fois que vous aurez confirmé cette adresse, nous remplacerons votre adresse e-mail actuelle par celle-ci (%1).", - "welcome.text1": "Merci de vous être inscrit sur %1!", - "welcome.text2": "Pour activer totalement votre compte, nous devons vérifier que vous êtes bien propriétaire de l'adresse email que vous avez utilisée pour vous inscrire.", - "welcome.text3": "Un administrateur a accepté votre demande d'inscription. Vous pouvez maintenant vous connecter avec vos identifiants/mots de passe.", + "welcome.text1": "Merci de vous être inscrit sur %1 !", + "welcome.text2": "Pour activer complètement votre compte, nous devons vérifier que vous êtes bien le propriétaire de l'adresse e-mail utilisée lors de votre inscription.", + "welcome.text3": "Un administrateur a accepté votre demande d'inscription. Vous pouvez maintenant vous connecter avec vos identifiants.", "welcome.cta": "Cliquer ici pour confirmer votre adresse e-mail", "invitation.text1": "%1 vous a invité à rejoindre %2", - "invitation.text2": "Votre invitation va expirer dans %1 jours.", - "invitation.cta": "Cliquer ici pour créer votre compte.", + "invitation.text2": "Votre invitation expirera dans %1 jours.", + "invitation.cta": "Cliquer ici pour créer votre compte", "reset.text1": "Nous avons reçu une demande de réinitialisation de votre mot de passe, probablement parce que vous l'avez oublié. Si ce n'est pas le cas, veuillez ignorer cet e-mail.", "reset.text2": "Pour confirmer la réinitialisation de votre mot de passe, veuillez cliquer sur le lien suivant :", "reset.cta": "Cliquer ici pour réinitialiser votre mot de passe", "reset.notify.subject": "Mot de passe modifié", "reset.notify.text1": "Nous vous informons que le %1, votre mot de passe a été modifié.", - "reset.notify.text2": "Si vous n'avez pas autorisé ceci, veuillez contacter immédiatement un administrateur.", + "reset.notify.text2": "Si vous n'avez pas autorisé cette modification, veuillez contacter immédiatement un administrateur.", "digest.unread-rooms": "Discussions non lues", - "digest.room-name-unreadcount": "%1 (%2 non lu)", + "digest.room-name-unreadcount": "%1 (%2 non lus)", "digest.latest-topics": "Derniers sujets de %1 :", "digest.top-topics": "Meilleurs sujets de %1", "digest.popular-topics": "Sujets populaires de %1", - "digest.cta": "Cliquer ici pour aller sur %1", + "digest.cta": "Cliquer ici pour accéder à %1", "digest.unsub.info": "Cette lettre d'activités vous a été envoyée en raison de vos paramètres d'abonnement.", "digest.day": "jour", "digest.week": "semaine", @@ -35,24 +35,24 @@ "digest.subject": "Lettre d'activités de %1", "digest.title.day": "Votre lettre d'activités quotidienne", "digest.title.week": "Votre lettre d'activités hebdomadaire", - "digest.title.month": "Votre lettre d'activités mensuel", - "notif.chat.new-message-from-user": "New message from \"%1\"", - "notif.chat.new-message-from-user-in-room": "New message from %1 in room %2", + "digest.title.month": "Votre lettre d'activités mensuelle", + "notif.chat.new-message-from-user": "Nouveau message de \"%1\"", + "notif.chat.new-message-from-user-in-room": "Nouveau message de %1 dans la discussion %2", "notif.chat.cta": "Cliquer ici pour continuer la conversation", - "notif.chat.unsub.info": "Cette notification de chat a été envoyé en raison de vos paramètres d'abonnement.", - "notif.post.unsub.info": "La notification de ce message vous a été envoyé en raison de vos paramètres d'abonnement.", + "notif.chat.unsub.info": "Cette notification de chat vous a été envoyée en raison de vos paramètres d'abonnement.", + "notif.post.unsub.info": "La notification de ce message vous a été envoyée en raison de vos paramètres d'abonnement.", "notif.post.unsub.one-click": "Vous pouvez également vous désabonner des lettres d'activités en cliquant sur", "notif.cta": "Sur le forum", "notif.cta-new-reply": "Voir les messages", "notif.cta-new-chat": "Voir les discussions", "notif.test.short": "Tester les notifications", - "notif.test.long": "Ceci est un test de notifications de mail. Envoyez de l'aide !", - "test.text1": "Ceci est un e-mail de test pour vérifier que leur envoi est correctement configuré pour NodeBB.", + "notif.test.long": "Ceci est un test de notifications par e-mail. Envoyez de l'aide !", + "test.text1": "Ceci est un e-mail de test pour vérifier que l’envoi de mails est correctement configuré pour NodeBB.", "unsub.cta": "Cliquer ici pour modifier ces paramètres", "unsubscribe": "Se désinscrire", - "unsub.success": "Vous ne recevrez plus d'e-mails de la liste de diffusion %1", + "unsub.success": "Vous ne recevrez plus d’e-mails de la liste de diffusion %1", "unsub.failure.title": "Impossible de se désinscrire", - "unsub.failure.message": "Malheureusement, nous n'avons pas pu vous désinscrire de la liste de diffusion, car il y avait un problème avec le lien. Cependant, vous pouvez modifier vos préférences de messagerie en accédant à vos paramètres utilisateur.

(erreur : %1)", + "unsub.failure.message": "Malheureusement, nous n'avons pas pu vous désinscrire de la liste de diffusion en raison d’un problème avec le lien. Cependant, vous pouvez modifier vos préférences de messagerie en accédant à vos paramètres utilisateur.

(Erreur : %1)", "banned.subject": "Vous avez été banni de %1", "banned.text1": "L'utilisateur %1 a été banni de %2.", "banned.text2": "Ce ban est effectif jusqu'au %1.", diff --git a/public/language/fr/error.json b/public/language/fr/error.json index c74a12c534..585541611a 100644 --- a/public/language/fr/error.json +++ b/public/language/fr/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Données invalides", + "invalid-config-field-value": "Valeur invalide pour le champ de configuration '%1' : %2", "invalid-json": "JSON invalide", "wrong-parameter-type": "Une valeur de type %3 était attendue pour la propriété `%1`, mais %2 a été reçu à la place", "required-parameters-missing": "Les paramètres requis étaient manquants dans cet appel d'API : %1", @@ -32,7 +33,7 @@ "invalid-path": "Chemin invalide", "folder-exists": "Le dossier existe", "invalid-pagination-value": "Valeur de pagination invalide. Celle-ci doit être comprise entre %1 et %2.", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "Valeur de « non lu » invalide : elle doit être comprise entre 1 et %1", "username-taken": "Ce nom d'utilisateur est déjà pris", "email-taken": "Cet e-mail est déjà utilisé.", "email-nochange": "Le mail saisi est déjà enregistré.", @@ -192,10 +193,10 @@ "custom-user-field-value-too-long": "La valeur du champ personnalisé est trop longue, %1", "custom-user-field-select-value-invalid": "L’option sélectionnée du champ personnalisé n’est pas valide, %1", "custom-user-field-invalid-text": "Le texte du champ personnalisé n’est pas valide, %1", - "custom-user-field-invalid-link": "Custom field link is invalid, %1", - "custom-user-field-invalid-number": "Custom field number is invalid, %1", - "custom-user-field-invalid-date": "Custom field date is invalid, %1", - "invalid-custom-user-field": "Invalid custom user field, \"%1\" is already used by NodeBB", + "custom-user-field-invalid-link": "Le lien du champ personnalisé est invalide : %1", + "custom-user-field-invalid-number": "Le numéro du champ personnalisé est invalide : %1", + "custom-user-field-invalid-date": "La date du champ personnalisé est invalide : %1", + "invalid-custom-user-field": "Champ utilisateur personnalisé invalide : « %1 » existe déjà dans NodeBB.", "post-already-flagged": "Vous avez déjà signalé ce message", "user-already-flagged": "Vous avez déjà signalé cet utilisateur", "post-flagged-too-many-times": "Ce message a déjà été signalé par d'autres", @@ -230,7 +231,7 @@ "no-topics-selected": "Aucun sujet sélectionné !", "cant-move-to-same-topic": "Impossible de déplacer le message dans le même sujet !", "cant-move-topic-to-same-category": "Impossible de déplacer le sujet dans la même catégorie !", - "cant-move-topic-to-from-remote-categories": "You cannot move topics in or out of remote categories; consider cross-posting instead.", + "cant-move-topic-to-from-remote-categories": "Vous ne pouvez pas déplacer de sujets vers ou depuis des catégories distantes ; envisagez plutôt de les publier en croisé.", "cannot-block-self": "Vous ne pouvez pas vous bloquer !", "cannot-block-privileged": "Vous ne pouvez pas bloquer les administrateurs ou les modérateurs globaux", "cannot-block-guest": "Les Invités ne peuvent pas bloquer d'autres utilisateurs", @@ -240,12 +241,12 @@ "socket-reconnect-failed": "Serveur inaccessible pour le moment. Cliquez ici pour réessayer ou réessayez plus tard", "invalid-plugin-id": "ID de plugin invalide", "plugin-not-whitelisted": "Impossible d'installer le plugin, seuls les plugins mis en liste blanche dans le gestionnaire de packages NodeBB peuvent être installés via l'ACP", - "cannot-toggle-system-plugin": "You cannot toggle the state of a system plugin", - "plugin-installation-via-acp-disabled": "Plugin installation via ACP is disabled", + "cannot-toggle-system-plugin": "L’activation ou la désactivation d’un plugin système n’est pas autorisée", + "plugin-installation-via-acp-disabled": "L’installation de plugins via le Panneau d’administration est désactivée", "plugins-set-in-configuration": "Vous n'êtes pas autorisé à modifier l'état des plugins car ils sont définis au moment de l'exécution (config.json, variables d'environnement ou arguments de terminal), veuillez plutôt modifier la configuration.", "theme-not-set-in-configuration": "Lors de la définition des plugins actifs, le changement de thème nécessite d'ajouter le nouveau thème à la liste des plugins actifs avant de le mettre à jour dans l'ACP", "topic-event-unrecognized": "Événement du sujet '%1' non reconnu", - "category.handle-taken": "Category handle is already taken, please choose another.", + "category.handle-taken": "L’identifiant de la catégorie est déjà pris, veuillez en choisir un autre.", "cant-set-child-as-parent": "Cette catégorie ne peut être une catégorie principale", "cant-set-self-as-parent": "Ne peut être définie comme catégorie principale", "api.master-token-no-uid": "Un jeton principal a été reçu sans `_uid` correspondant dans le corps de la requête", @@ -253,7 +254,7 @@ "api.401": "Aucune session de connexion valide trouvée. Veuillez vous connecter et réessayer.", "api.403": "Vous n'êtes pas autorisé à réaliser cet appel", "api.404": "Appel de l'API non valide", - "api.413": "The request payload is too large", + "api.413": "La taille de la requête est trop importante", "api.426": "HTTPS est requis pour les demandes d’écriture via l'API, veuillez renvoyer votre demande via HTTPS", "api.429": "Vous avez fait trop de demandes, veuillez réessayer plus tard", "api.500": "Une erreur inattendue s'est produite lors de la tentative de traitement de votre demande.", @@ -261,10 +262,10 @@ "api.503": "L'accès n'est pas disponible actuellement en raison de la configuration du serveur", "api.reauth-required": "La ressource à laquelle vous tentez d'accéder nécessite une (ré-)authentification.", "activitypub.not-enabled": "La fédération n'est pas activée sur ce serveur.", - "activitypub.invalid-id": "Unable to resolve the input id, likely as it is malformed.", - "activitypub.get-failed": "Unable to retrieve the specified resource.", - "activitypub.pubKey-not-found": "Unable to resolve public key, so payload verification cannot take place.", - "activitypub.origin-mismatch": "The received object's origin does not match the sender's origin", - "activitypub.actor-mismatch": "The received activity is being carried out by an actor that is different from expected.", - "activitypub.not-implemented": "The request was denied because it or an aspect of it is not implemented by the recipient server" + "activitypub.invalid-id": "Impossible de traiter l’ID saisi, il semble incorrect.", + "activitypub.get-failed": "Impossible de récupérer la ressource spécifiée", + "activitypub.pubKey-not-found": "La clé publique est introuvable, la vérification de la charge utile est impossible.", + "activitypub.origin-mismatch": "L’origine de l’objet reçu est différente de celle de l’expéditeur", + "activitypub.actor-mismatch": "L’activité reçue est effectuée par un acteur différent de celui attendu", + "activitypub.not-implemented": "La requête a été rejetée : elle n’est pas prise en charge par le serveur destinataire." } \ No newline at end of file diff --git a/public/language/fr/flags.json b/public/language/fr/flags.json index 30223e8eba..02954f224f 100644 --- a/public/language/fr/flags.json +++ b/public/language/fr/flags.json @@ -84,17 +84,17 @@ "modal-reason-offensive": "Choquant", "modal-reason-other": "Autre (précisez ci-dessous)", "modal-reason-custom": "Motif du signalement...", - "modal-notify-remote": "Forward this report to %1", + "modal-notify-remote": "Envoyer ce rapport à %1", "modal-submit": "Soumettre", "modal-submit-success": "Le contenu a été soumis pour examen.", - "modal-confirm-rescind": "Rescind Report?", + "modal-confirm-rescind": "Annuler le signalement ?", "bulk-actions": "Actions en vrac", "bulk-resolve": "Signalement(s) résolu(s)", - "confirm-purge": "Are you sure you want to permanently delete these flags?", - "purge-cancelled": "Flag Purge Cancelled", - "bulk-purge": "Purge Flag(s)", + "confirm-purge": "Êtes-vous sûr de vouloir supprimer définitivement ces signalements ?", + "purge-cancelled": "Suppression des signalements annulée", + "bulk-purge": "Supprimer le(s) signalement(s)", "bulk-success": "%1 signalements mis à jour", "flagged-timeago": "Signalé ", "auto-flagged": "[Auto Signalement] A reçu %1 votes négatifs." diff --git a/public/language/fr/global.json b/public/language/fr/global.json index f5e9e3d3f7..e9751bc1a7 100644 --- a/public/language/fr/global.json +++ b/public/language/fr/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "Les types de fichiers autorisés sont : %1", "unsaved-changes": "Vous avez des modifications non sauvegardées. Êtes-vous sûr de vouloir naviguer tout de même ?", "reconnecting-message": "Il semble que votre connexion à %1 ait été perdue, veuillez patienter pendant que nous vous reconnectons.", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "Connecté à %1 avec succès.", "play": "Lire", "cookies.message": "Ce site utilise des cookies pour vous permettre d'avoir la meilleure expérience possible.", "cookies.accept": "Compris !", diff --git a/public/language/fr/groups.json b/public/language/fr/groups.json index f946d20072..2a4246edd5 100644 --- a/public/language/fr/groups.json +++ b/public/language/fr/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "Groupe", "all-groups": "Tous les groupes", "groups": "Groupes", "members": "Membres", - "x-members": "%1 member(s)", + "x-members": "%1 membre(s)", "view-group": "Voir le groupe", "owner": "Propriétaire du groupe", "new-group": "Créer un nouveau groupe", diff --git a/public/language/fr/modules.json b/public/language/fr/modules.json index 007cdb8793..31e4c4a9e3 100644 --- a/public/language/fr/modules.json +++ b/public/language/fr/modules.json @@ -48,7 +48,7 @@ "chat.add-user": "Ajouter un utilisateur", "chat.notification-settings": "Paramètres de notification", "chat.default-notification-setting": "Paramètres de notification par défaut", - "chat.join-leave-messages": "Join/Leave Messages", + "chat.join-leave-messages": "Rejoindre/Quitter les messages", "chat.notification-setting-room-default": "Salon par défaut", "chat.notification-setting-none": "Aucune notification", "chat.notification-setting-at-mention-only": "@mention seulement", @@ -82,7 +82,7 @@ "composer.hide-preview": "Masquer l'aperçu", "composer.help": "Aide", "composer.user-said-in": "%1 a dit dans %2 :", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [a dit](%2):", "composer.discard": "Êtes-vous sûr de bien vouloir supprimer ce message ?", "composer.submit-and-lock": "Envoyer et verrouiller", "composer.toggle-dropdown": "Afficher/masquer le menu", @@ -116,8 +116,8 @@ "composer.discard-all-drafts": "Supprimer tous les brouillons", "composer.no-drafts": "Vous n'avez pas de brouillons", "composer.discard-draft-confirm": "Voulez-vous supprimer ce brouillon ?", - "composer.remote-pid-editing": "Editing a remote post", - "composer.remote-pid-content-immutable": "The content of remote posts cannot be edited. However, you are able change the topic title and tags.", + "composer.remote-pid-editing": "Modifier un post distant", + "composer.remote-pid-content-immutable": "Le contenu des posts distants ne peut pas être modifié. Cependant, vous pouvez changer le titre du sujet et les tags.", "bootbox.ok": "OK", "bootbox.cancel": "Annuler", "bootbox.confirm": "Confirmer", diff --git a/public/language/fr/notifications.json b/public/language/fr/notifications.json index ba71787e7f..6e11615ac6 100644 --- a/public/language/fr/notifications.json +++ b/public/language/fr/notifications.json @@ -9,38 +9,38 @@ "continue-to": "Continuer vers %1", "return-to": "Revenir à %1", "new-notification": "Vous avez une nouvelle notification", - "you-have-unread-notifications": "Vous avez des notifications non-lues", + "you-have-unread-notifications": "Vous avez des notifications non lues", "all": "Tout", "topics": "Sujets", "tags": "Mots-clés", "categories": "Catégories", "replies": "Réponses", "chat": "Discussions", - "group-chat": "Groupe de discussions", - "public-chat": "Discussions publiques", - "follows": "Suivis", + "group-chat": "Discussion de groupe", + "public-chat": "Discussion publique", + "follows": "Abonnements", "upvote": "Votes positifs", "awards": "Récompenses", "new-flags": "Nouveaux signalements", "my-flags": "Mes signalements", "bans": "Bannissements", "new-message-from": "Nouveau message de %1", - "new-messages-from": "%1 Nouveaux messages de %2", + "new-messages-from": "%1 nouveaux messages de %2", "new-message-in": "Nouveau message dans %1", - "new-messages-in": "%1 Nouveaux messages dans %2", - "user-posted-in-public-room": "%1 wrote in %3", - "user-posted-in-public-room-dual": "%1 and %2 wrote in %4", - "user-posted-in-public-room-triple": "%1, %2 and %3 wrote in %5", - "user-posted-in-public-room-multiple": "%1, %2 and %3 others wrote in %5", + "new-messages-in": "%1 nouveaux messages dans %2", + "user-posted-in-public-room": "%1 a écrit dans %3", + "user-posted-in-public-room-dual": "%1 et %2 ont écrit dans %4", + "user-posted-in-public-room-triple": "%1, %2 et %3 ont écrit dans %5", + "user-posted-in-public-room-multiple": "%1, %2 et %3 autres ont écrit dans %5", "upvoted-your-post-in": "%1 a approuvé votre publication dans %2", "upvoted-your-post-in-dual": "%1 et %2 ont approuvé votre publication dans %3", "upvoted-your-post-in-triple": "%1, %2 et %3 ont approuvé votre publication dans %4", - "upvoted-your-post-in-multiple": "%1, %2 et %3 autres ont approuvé votre publication dans %4.", + "upvoted-your-post-in-multiple": "%1, %2 et %3 autres ont approuvé votre publication dans %4", "moved-your-post": "%1 a déplacé votre publication vers %2", - "moved-your-topic": "%1 a déplacé %2.", + "moved-your-topic": "%1 a déplacé %2", "user-flagged-post-in": "%1 a signalé une publication dans %2", "user-flagged-post-in-dual": "%1 et %2 ont signalé une publication dans %3", - "user-flagged-post-in-triple": "1, %2 et %3 ont signalé une publication dans %4", + "user-flagged-post-in-triple": "%1, %2 et %3 ont signalé une publication dans %4", "user-flagged-post-in-multiple": "%1, %2 et %3 autres ont signalé une publication dans %4", "user-flagged-user": "%1 a signalé un profil utilisateur (%2)", "user-flagged-user-dual": "%1 et %2 ont signalé un profil utilisateur (%3)", @@ -49,59 +49,59 @@ "user-posted-to": "%1 a répondu dans %2", "user-posted-to-dual": "%1 et %2 ont répondu dans %3", "user-posted-to-triple": "%1, %2 et %3 ont répondu dans %4", - "user-posted-to-multiple": "%1, %2 and %3 autres ont répondu dans %4", + "user-posted-to-multiple": "%1, %2 et %3 autres ont répondu dans %4", "user-posted-topic": "%1 a publié %2", "user-edited-post": "%1 a édité une publication dans %2", "user-posted-topic-with-tag": "%1 a publié %2 (a mentionné %3)", - "user-posted-topic-with-tag-dual": "%1 a posté %2 (a mentionné %3 et %4)", - "user-posted-topic-with-tag-triple": "%1 a publié %2 (a mentionné %3, %4, et %5)", + "user-posted-topic-with-tag-dual": "%1 a publié %2 (a mentionné %3 et %4)", + "user-posted-topic-with-tag-triple": "%1 a publié %2 (a mentionné %3, %4 et %5)", "user-posted-topic-with-tag-multiple": "%1 a publié %2 (a mentionné %3)", "user-posted-topic-in-category": "%1 a publié %2 dans %3", "user-started-following-you": "%1 a commencé à vous suivre", "user-started-following-you-dual": "%1 et %2 ont commencé à vous suivre", - "user-started-following-you-triple": "%1, %2 et %3 ont commencé à vous suivre.", - "user-started-following-you-multiple": "%1, %2 et %3 autres ont commencé à vous suivre.", - "new-register": "%1 a envoyé une demande d'incription.", - "new-register-multiple": "Il y a %1 demandes d'inscription en attente de validation.", + "user-started-following-you-triple": "%1, %2 et %3 ont commencé à vous suivre", + "user-started-following-you-multiple": "%1, %2 et %3 autres ont commencé à vous suivre", + "new-register": "%1 a envoyé une demande d'inscription", + "new-register-multiple": "Il y a %1 demandes d'inscription en attente de validation", "flag-assigned-to-you": "Le signalement %1 vous a été assigné", "post-awaiting-review": "Message en attente de validation", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "Sujet en attente de validation", "profile-exported": "%1 profil exporté, cliquez pour le télécharger", "posts-exported": "%1 messages exportés, cliquez pour les télécharger", "uploads-exported": "%1 envois exportés, cliquez pour les télécharger", - "users-csv-exported": "Utilisateurs exportés en CSV, cliquer pour télécharger", + "users-csv-exported": "Utilisateurs exportés en CSV, cliquez pour télécharger", "post-queue-accepted": "Votre publication a été acceptée. Cliquez ici pour l'afficher.", "post-queue-rejected": "Votre publication a été rejetée.", - "post-queue-rejected-for-reason": "Votre publication en attente a été refusée pour le motif suivant : \"%1\"", + "post-queue-rejected-for-reason": "Votre publication a été rejetée pour le motif suivant : \"%1\"", "post-queue-notify": "Une publication en attente a reçu une notification : \"%1\"", "email-confirmed": "E-mail vérifié", "email-confirmed-message": "Merci pour la validation de votre adresse e-mail. Votre compte est désormais activé.", - "email-confirm-error-message": "Il y a un un problème dans la vérification de votre adresse e-mail. Le code est peut être invalide ou a expiré.", - "email-confirm-sent": "E-mail de vérification envoyé.", - "none": "aucun", + "email-confirm-error-message": "Problème lors de la vérification de votre e-mail. Le code est peut-être invalide ou expiré.", + "email-confirm-sent": "E-mail de vérification envoyé", + "none": "Aucun", "notification-only": "Notification uniquement", "email-only": "E-mail uniquement", "notification-and-email": "Notification & E-mail", - "notificationType-upvote": "Quand quelqu'un a voté pour une de vos publication", + "notificationType-upvote": "Quand quelqu'un vote pour une de vos publications", "notificationType-new-topic": "Quand quelqu'un que vous suivez publie un sujet", - "notificationType-new-topic-with-tag": "Quand un sujet est publié avec un mot-clé que vous suivez", - "notificationType-new-topic-in-category": "When a topic is posted in a watched category", - "notificationType-new-reply": "When a reply is posted in a watched topic", - "notificationType-post-edit": "When a post is edited in a watched topic", + "notificationType-new-topic-with-tag": "Quand un sujet avec un mot-clé que vous suivez est publié", + "notificationType-new-topic-in-category": "Quand un sujet dans une catégorie que vous suivez est publié", + "notificationType-new-reply": "Quand une nouvelle réponse est ajoutée dans un sujet que vous suivez", + "notificationType-post-edit": "Quand un message est modifié dans un sujet que vous suivez", "notificationType-follow": "Quand quelqu'un commence à vous suivre", - "notificationType-new-chat": "Quand vous recevez un message du chat", + "notificationType-new-chat": "Quand vous recevez un message de chat", "notificationType-new-group-chat": "Quand vous recevez un message de discussion de groupe", - "notificationType-new-public-chat": "Quand vous recevez un message du groupe de discussion publique", - "notificationType-group-invite": "Quand vous recevez une invitation d'un groupe", + "notificationType-new-public-chat": "Quand vous recevez un message dans le groupe de discussion publique", + "notificationType-group-invite": "Quand vous recevez une invitation à un groupe", "notificationType-group-leave": "Quand un utilisateur quitte votre groupe", - "notificationType-group-request-membership": "When a user requests to join a group you own", + "notificationType-group-request-membership": "Quand quelqu'un demande à rejoindre un groupe que vous administrez", "notificationType-new-register": "Quand quelqu'un est ajouté à la file d'attente d'inscription", "notificationType-post-queue": "Quand un nouveau message est mis en file d'attente", - "notificationType-new-post-flag": "Quand un message est marqué", + "notificationType-new-post-flag": "Quand un message est signalé", "notificationType-new-user-flag": "Quand un utilisateur est signalé", "notificationType-new-reward": "Quand vous gagnez une nouvelle récompense", - "activitypub.announce": "%1 a partagé votre publication dans %2 avec ses abonnés.", - "activitypub.announce-dual": "%1 et %2 ont partagé votre publication dans %3 avec leurs abonnés.", - "activitypub.announce-triple": "%1, %2 et %3 ont partagé votre publication dans %4 avec leurs abonnés.", - "activitypub.announce-multiple": "%1, %2 et %3 autres ont partagé votre publication à %4 avec leurs abonnés." + "activitypub.announce": "%1 a partagé votre publication dans %2 avec ses abonnés", + "activitypub.announce-dual": "%1 et %2 ont partagé votre publication dans %3 avec leurs abonnés", + "activitypub.announce-triple": "%1, %2 et %3 ont partagé votre publication dans %4 avec leurs abonnés", + "activitypub.announce-multiple": "%1, %2 et %3 autres ont partagé votre publication dans %4 avec leurs abonnés" } \ No newline at end of file diff --git a/public/language/fr/pages.json b/public/language/fr/pages.json index c636c03bbc..09afe8a8cc 100644 --- a/public/language/fr/pages.json +++ b/public/language/fr/pages.json @@ -36,7 +36,7 @@ "chat": "Conversation avec %1", "flags": "Signalements", "flag-details": "Détails signalement %1", - "world": "World", + "world": "Web", "account/edit": "Édition de \"%1\"", "account/edit/password": "Édition du mot de passe de \"%1\"", "account/edit/username": "Édition du nom d'utilisateur de \"%1\"", @@ -63,7 +63,7 @@ "account/blocks": "Utilisateurs bloqués pour %1", "account/uploads": "Envoyé par %1", "account/sessions": "Sessions des connexions", - "account/shares": "Topics shared by %1", + "account/shares": "Sujets partagés par %1", "confirm": "E-mail vérifié", "maintenance.text": "%1 est actuellement en cours de maintenance.
Veuillez revenir ultérieurement.", "maintenance.messageIntro": "De plus, l'administrateur a laissé ce message :", diff --git a/public/language/fr/recent.json b/public/language/fr/recent.json index 4f8e2a3532..989069f072 100644 --- a/public/language/fr/recent.json +++ b/public/language/fr/recent.json @@ -8,6 +8,6 @@ "no-recent-topics": "Il n'y a aucun sujet récent.", "no-popular-topics": "Il n'y a pas de sujet populaire.", "load-new-posts": "Charger les nouveaux messages", - "uncategorized.title": "All known topics", - "uncategorized.intro": "This page shows a chronological listing of every topic that this forum has received.
The views and opinions expressed in the topics below are not moderated and may not represent the views and opinions of this website." + "uncategorized.title": "Tous les sujets connus", + "uncategorized.intro": "Cette page présente la liste chronologique de tous les sujets abordés sur ce forum. Les opinions exprimées dans les sujets ci-dessous ne sont pas modérées et ne reflètent pas nécessairement celles de ce site web." } \ No newline at end of file diff --git a/public/language/fr/social.json b/public/language/fr/social.json index b2b66a6cf6..07e517ed2b 100644 --- a/public/language/fr/social.json +++ b/public/language/fr/social.json @@ -9,6 +9,6 @@ "continue-with-facebook": "Continuer avec Facebook", "sign-in-with-linkedin": "Connectez-vous avec LinkedIn", "sign-up-with-linkedin": "Inscrivez-vous avec LinkedIn", - "sign-in-with-wordpress": "Sign in with WordPress", - "sign-up-with-wordpress": "Sign up with WordPress" + "sign-in-with-wordpress": "Connectez-vous avec Wordpress", + "sign-up-with-wordpress": "Inscrivez-vous avec Wordpress" } \ No newline at end of file diff --git a/public/language/fr/themes/harmony.json b/public/language/fr/themes/harmony.json index 57e925ff5d..f60ed48c44 100644 --- a/public/language/fr/themes/harmony.json +++ b/public/language/fr/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Thème Harmony", "skins": "Habillages", - "light": "Light", - "dark": "Dark", + "light": "Clair", + "dark": "Sombre", "collapse": "Réduire", "expand": "Développer", "sidebar-toggle": "Réduire la barre latérale", @@ -15,11 +15,11 @@ "settings.mobileTopicTeasers": "Afficher les teasers de sujet sur mobile", "settings.stickyToolbar": "Barre d'outils", "settings.stickyToolbar.help": "La barre d'outils sur les pages de sujets et de catégories restera en haut de la page", - "settings.topicSidebarTools": "Topic sidebar tools", - "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", - "settings.autohideBottombar": "Auto hide mobile navigation bar", - "settings.autohideBottombar.help": "The mobile bar will be hidden when the page is scrolled down", - "settings.topMobilebar": "Move the mobile navigation bar to the top", + "settings.topicSidebarTools": "Outils de la barre latérale du sujet", + "settings.topicSidebarTools.help": "En activant cette option, les outils du sujet seront affichés dans la barre latérale sur ordinateur", + "settings.autohideBottombar": "Masquer automatiquement la barre inférieure", + "settings.autohideBottombar.help": "La barre inférieure sur mobile sera masquée lorsque la page défilera vers le bas", + "settings.topMobilebar": "Placer la barre de navigation mobile en haut de l’écran", "settings.openSidebars": "Barres latérales ouvertes", "settings.chatModals": "Activer les discussions" } \ No newline at end of file diff --git a/public/language/fr/topic.json b/public/language/fr/topic.json index 3544e3b361..c1d8676507 100644 --- a/public/language/fr/topic.json +++ b/public/language/fr/topic.json @@ -35,7 +35,7 @@ "locked": "Verrouillé", "pinned": "Épinglé", "pinned-with-expiry": "Épinglé jusqu'au %1", - "scheduled": "Planifier", + "scheduled": "Planifié", "deleted": "Supprimé", "moved": "Déplacé", "moved-from": "Déplacé de %1", @@ -225,7 +225,7 @@ "no-more-next-post": "Vous n'avez plus de messages dans ce sujet", "open-composer": "Ouvrir l'éditeur", "post-quick-reply": "Réponse rapide", - "post-quick-create": "Quick post", + "post-quick-create": "Message rapide", "navigator.index": "Message %1 sur %2", "navigator.unread": "%1 non lu", "upvote-post": "Vote positif", @@ -235,7 +235,7 @@ "thumb-image": "Vignette du sujet", "announcers": "Partages", "announcers-x": "Partages (%1)", - "guest-cta.title": "Hello! It looks like you're interested in this conversation, but you don't have an account yet.", - "guest-cta.message": "Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.", - "guest-cta.closing": "With your input, this post could be even better 💗" + "guest-cta.title": "Bonjour ! Vous semblez intéressé par cette conversation, mais vous n’avez pas encore de compte.", + "guest-cta.message": "Marre de refaire défiler les mêmes messages ? Créez un compte pour retrouver votre position, recevoir des notifications des nouvelles réponses, sauvegarder vos favoris et voter pour les messages que vous appréciez.", + "guest-cta.closing": "Grâce à votre participation, ce message peut devenir encore meilleur 💗" } \ No newline at end of file diff --git a/public/language/fr/unread.json b/public/language/fr/unread.json index 8c729018de..d06a109783 100644 --- a/public/language/fr/unread.json +++ b/public/language/fr/unread.json @@ -1,5 +1,5 @@ { - "title": "Non lu", + "title": "Non lus", "no-unread-topics": "Aucun sujet non lu.", "load-more": "Charger la suite", "mark-as-read": "Marquer comme lu", diff --git a/public/language/fr/user.json b/public/language/fr/user.json index 1310dfd429..e95f2292c5 100644 --- a/public/language/fr/user.json +++ b/public/language/fr/user.json @@ -3,9 +3,9 @@ "banned": "Banni", "unbanned": "Débannir", "muted": "Muet", - "unmuted": "Rétablir la possibilité d'écrire / répondre ", + "unmuted": "Rétablir la possibilité d'écrire/répondre", "offline": "Hors-ligne", - "deleted": "Effacé", + "deleted": "Supprimé", "username": "Nom d'utilisateur", "joindate": "Date d'inscription", "postcount": "Nombre de messages", @@ -14,21 +14,21 @@ "account-info": "Informations du compte", "admin-actions-label": "Modération", "ban-account": "Bannir le compte", - "ban-account-confirm": "Êtes-vous sûr de bien vouloir bannir cet utilisateur ?", + "ban-account-confirm": "Êtes-vous sûr de vouloir bannir cet utilisateur ?", "unban-account": "Rétablir le compte", - "mute-account": "Compte muet", - "unmute-account": "Compte actif", + "mute-account": "Mettre en sourdine", + "unmute-account": "Rétablir le compte", "delete-account": "Supprimer le compte", "delete-account-as-admin": "Supprimer le compte", "delete-content": "Supprimer le contenu du compte", "delete-all": "Supprimer le compte et le contenu", - "delete-account-confirm": "Êtes-vous sûr de vouloir supprimer votre compte ?
Cette action est irréversible et vous ne pourrez récupérer aucune de vos données

Entrez votre mot de passe pour confirmer que vous souhaitez détruire ce compte.", - "delete-this-account-confirm": "Êtes-vous sûr de vouloir supprimer ce compte ?
Cette action est irréversible, les messages deviendront anonymes et vous ne pourrez pas restaurer les messages associés avec le compte supprimé.

", - "delete-account-content-confirm": "Êtes-vous sûr de vouloir supprimer le contenu de ce compte (messages / sujets / fichiers envoyés) ?
Cette action est irréversible et vous ne pourrez récupérer aucune donnée.

", - "delete-all-confirm": "Êtes-vous sûr de vouloir supprimer ce compte et tout son contenu (messages / sujets / fichiers envoyés) ?
Cette action est irréversible et vous ne pourrez récupérer aucune donnée.

", + "delete-account-confirm": "Êtes-vous sûr de vouloir supprimer votre compte ?
Cette action est irréversible et toutes vos données seront perdues.

Entrez votre mot de passe pour confirmer la suppression.", + "delete-this-account-confirm": "Êtes-vous sûr de vouloir supprimer ce compte ?
Cette action est irréversible, les messages deviendront anonymes et ne pourront pas être restaurés.

", + "delete-account-content-confirm": "Êtes-vous sûr de vouloir supprimer le contenu de ce compte (messages, sujets, fichiers envoyés) ?
Cette action est irréversible et toutes les données seront perdues.

", + "delete-all-confirm": "Êtes-vous sûr de vouloir supprimer ce compte et tout son contenu (messages, sujets, fichiers envoyés) ?
Cette action est irréversible et toutes les données seront perdues.

", "account-deleted": "Compte supprimé", "account-content-deleted": "Contenu du compte supprimé", - "fullname": "Nom", + "fullname": "Nom complet", "website": "Site web", "location": "Localisation", "age": "Âge", @@ -39,8 +39,8 @@ "reputation": "Réputation", "bookmarks": "Marque-pages", "watched-categories": "Catégories surveillées", - "watched-tags": "Mot-clés surveillés", - "change-all": "Tout changer", + "watched-tags": "Mots-clés surveillés", + "change-all": "Tout modifier", "watched": "Abonnements", "ignored": "Ignorés", "read": "Lu", @@ -66,74 +66,74 @@ "unfollow": "Se désabonner", "cancel-follow": "Annuler la demande de suivi", "more": "Plus", - "profile-update-success": "Le profil a bien été mis à jour !", + "profile-update-success": "Profil mis à jour avec succès !", "change-picture": "Changer l'image", "change-username": "Changer le nom d'utilisateur", "change-email": "Changer l'e-mail", "email-updated": "E-mail mis à jour", - "email-same-as-password": "Veuillez entrer votre mot de passe actuel pour continuer - vous devez saisir à nouveau votre e-mail", + "email-same-as-password": "Veuillez entrer votre mot de passe actuel pour continuer", "edit": "Éditer", "edit-profile": "Éditer le profil", "default-picture": "Icône par défaut", "uploaded-picture": "Image envoyée", - "upload-new-picture": "Envoyer une nouvelle image", - "upload-new-picture-from-url": "Envoyer une nouvelle image depuis un URL", + "upload-new-picture": "Téléverser une nouvelle image", + "upload-new-picture-from-url": "Téléverser depuis une URL", "current-password": "Mot de passe actuel", "new-password": "Nouveau mot de passe", "change-password": "Changer le mot de passe", - "change-password-error": "Mot de passe invalide !", - "change-password-error-wrong-current": "Votre mot de passe est incorrect !", - "change-password-error-same-password": "Votre nouveau mot de passe est identique à l'actuel, veuillez en utiliser un différent.", - "change-password-error-match": "Les mots de passe doivent être identiques !", - "change-password-error-privileges": "Vous n'avez pas les droits de changer ce mot de passe.", - "change-password-success": "Votre mot de passe a été mis à jour.", + "change-password-error": "Mot de passe invalide !", + "change-password-error-wrong-current": "Mot de passe actuel incorrect !", + "change-password-error-same-password": "Le nouveau mot de passe est identique à l'ancien. Veuillez en choisir un autre.", + "change-password-error-match": "Les mots de passe doivent correspondre !", + "change-password-error-privileges": "Vous n'avez pas les droits pour changer ce mot de passe.", + "change-password-success": "Mot de passe mis à jour avec succès.", "confirm-password": "Confirmer le mot de passe", "password": "Mot de passe", - "username-taken-workaround": "Le nom d'utilisateur souhaité est déjà utilisé, nous l'avons donc légèrement modifié. Vous êtes maintenant connu comme %1", - "password-same-as-username": "Votre mot de passe est identique à votre nom d'utilisateur. Veuillez en choisir un autre.", - "password-same-as-email": "Votre mot de passe est identique à votre adresse e-mail. Veuillez en choisir un autre.", - "weak-password": "Sécurité du mot de passe faible.", - "upload-picture": "Envoyer l'image", - "upload-a-picture": "Envoyer une image", + "username-taken-workaround": "Nom d'utilisateur déjà utilisé, renommé en %1", + "password-same-as-username": "Le mot de passe est identique au nom d'utilisateur. Veuillez en choisir un autre.", + "password-same-as-email": "Le mot de passe est identique à l'adresse e-mail. Veuillez en choisir un autre.", + "weak-password": "Mot de passe faible", + "upload-picture": "Téléverser l'image", + "upload-a-picture": "Téléverser une image", "remove-uploaded-picture": "Supprimer l'image envoyée", - "upload-cover-picture": "Envoyer une image de couverture", - "remove-cover-picture-confirm": "Êtes-vous sûr(e) de vouloir supprimer l'image de couverture ?", - "crop-picture": "Découper l’image", - "upload-cropped-picture": "Découper et envoyer", - "avatar-background-colour": "Couleur d'arrière plan", + "upload-cover-picture": "Téléverser une image de couverture", + "remove-cover-picture-confirm": "Êtes-vous sûr de vouloir supprimer l'image de couverture ?", + "crop-picture": "Recadrer l’image", + "upload-cropped-picture": "Recadrer et envoyer", + "avatar-background-colour": "Couleur de fond", "settings": "Paramètres", "show-email": "Afficher mon e-mail", "show-fullname": "Afficher mon nom complet", - "restrict-chats": "Autoriser la réception de messages ne provenant que des personnes auxquelles je suis abonné", - "disable-incoming-chats": "Disable incoming chat messages ", - "chat-allow-list": "Autoriser les messages de chat des utilisateurs suivants", - "chat-deny-list": "Refuser les messages de chat des utilisateurs suivants", + "restrict-chats": "Autoriser les messages uniquement des abonnés", + "disable-incoming-chats": "Désactiver les messages entrants", + "chat-allow-list": "Autoriser les messages de ces utilisateurs", + "chat-deny-list": "Refuser les messages de ces utilisateurs", "chat-list-add-user": "Ajouter un utilisateur", - "digest-label": "S’inscrire aux lettres de suivi d'activités", - "digest-description": "S'abonner par e-mail aux mises à jour de ce forum (nouvelles notifications et nouveaux sujets) selon le planning sélectionné.", + "digest-label": "S’inscrire aux lettres d'activité", + "digest-description": "Recevoir par e-mail les mises à jour du forum selon la fréquence choisie.", "digest-off": "Désactivé", "digest-daily": "Quotidien", "digest-weekly": "Hebdomadaire", - "digest-biweekly": "Bihebdomadaire ", + "digest-biweekly": "Bihebdomadaire", "digest-monthly": "Mensuel", - "has-no-follower": "Cet utilisateur n'a pas encore d'abonné :(", - "follows-no-one": "Cet utilisateur n'est abonné à personne :(", + "has-no-follower": "Aucun abonné pour cet utilisateur.", + "follows-no-one": "Cet utilisateur ne suit personne.", "has-no-posts": "Cet utilisateur n'a encore rien posté.", - "has-no-best-posts": "Cet utilisateur n'a pas encore d'avis positif.", + "has-no-best-posts": "Cet utilisateur n'a encore reçu aucun avis positif.", "has-no-topics": "Cet utilisateur n'a encore créé aucun sujet.", - "has-no-watched-topics": "Cet utilisateur ne s'est encore abonné à aucun sujet.", - "has-no-ignored-topics": "Cet utilisateur n'a encore ignoré aucun sujet.", - "has-no-read-topics": "Cet utilisateur n'a pas encore consulté de sujets.", - "has-no-upvoted-posts": "Cet utilisateur n'a pas encore donné d'avis positif.", - "has-no-downvoted-posts": "Cet utilisateur n'a pas donné d'avis négatif.", - "has-no-controversial-posts": "Cet utilisateur n'a pas encore d'avis négatif.", - "has-no-blocks": "Vous n'avez bloqué aucun utilisateur.", - "has-no-shares": "Cet utilisateur n'a partagé aucun sujet.", + "has-no-watched-topics": "Aucun sujet suivi par cet utilisateur.", + "has-no-ignored-topics": "Aucun sujet ignoré par cet utilisateur.", + "has-no-read-topics": "Cet utilisateur n'a encore consulté aucun sujet.", + "has-no-upvoted-posts": "Cet utilisateur n'a encore donné aucun avis positif.", + "has-no-downvoted-posts": "Cet utilisateur n'a encore donné aucun avis négatif.", + "has-no-controversial-posts": "Cet utilisateur n'a encore d'avis controversé.", + "has-no-blocks": "Aucun utilisateur bloqué.", + "has-no-shares": "Cet utilisateur n'a encore partagé aucun sujet.", "email-hidden": "E-mail masqué", - "hidden": "masqué", + "hidden": "Masqué", "paginate-description": "Utiliser la pagination des sujets et des messages à la place du défilement infini", - "topics-per-page": "Topics per page", - "posts-per-page": "Posts per page", + "topics-per-page": "Sujets par page", + "posts-per-page": "Messages par page", "category-topic-sort": "Tri des sujets par catégorie", "topic-post-sort": "Tri des articles par sujet", "max-items-per-page": "Maximum %1", @@ -147,10 +147,10 @@ "upvote-notif-freq.logarithmic": "Les 10, 100, 1000...", "upvote-notif-freq.disabled": "Désactivé", "notification-type-web": "Web", - "notification-type-email": "Email", + "notification-type-email": "E-mail", "browsing": "Paramètres de navigation", - "unread.cutoff": "Unread cutoff (Maximum %1 days)", - "unread.cutoff-help": "Topics will be marked read if they have not been updated within this number of days.", + "unread.cutoff": "Limite de messages non lus (Maximum %1 jours)", + "unread.cutoff-help": "Les sujets seront marqués comme lus s’ils n’ont pas été mis à jour depuis ce nombre de jours.", "open-links-in-new-tab": "Ouvrir les liens externes dans un nouvel onglet", "enable-topic-searching": "Activer la recherche dans les sujets", "topic-search-help": "Une fois activé, la recherche dans les sujets va remplacer la recherche de page du navigateur et vous permettra de rechercher dans l'intégralité d'un sujet au lieu des seuls posts affichés à l'écran.", @@ -179,7 +179,7 @@ "sso.dissociate": "Dissocier", "sso.dissociate-confirm-title": "Confirmer la dissociation", "sso.dissociate-confirm": "Êtes-vous sûr de vouloir dissocier votre compte de %1 ?", - "info.invited-by": "Invited by", + "info.invited-by": "Invité par", "info.latest-flags": "Derniers signalements", "info.profile": "Profile", "info.post": "Message", diff --git a/public/language/fr/world.json b/public/language/fr/world.json index b238721bf7..d8467a263e 100644 --- a/public/language/fr/world.json +++ b/public/language/fr/world.json @@ -1,11 +1,13 @@ { "name": "Monde", - "latest": "Dernier", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", + "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", + "popular-day": "Populaires (Jour)", + "popular-week": "Populaires (Semaine)", + "popular-month": "Populaires (Mois)", + "popular-year": "Populaires (Année)", + "popular-alltime": "Populaires (Tout temps)", "recent": "Tous", "help": "Aide", @@ -16,10 +18,12 @@ "help.federating": "De même, si des utilisateurs extérieurs à ce forum commencent à vous suivre, vos publications commenceront à apparaître sur ces applications et sites web également.", "help.next-generation": "C'est la prochaine génération des réseaux sociaux, commencez à contribuer dès aujourd'hui !", - "onboard.title": "Votre fenêtre sur le fediverse...", - "onboard.what": "Voici votre catégorie personnalisée, composée uniquement de contenu trouvé en dehors de ce forum. La présence de contenu sur cette page dépend de si vous suivez la personne, ou si ce post a été partagé par quelqu'un que vous suivez.", - "onboard.why": "Il se passe beaucoup de choses en dehors de ce forum, et tout n'est pas nécessairement pertinent pour vos intérêts. C'est pourquoi suivre des personnes est le meilleur moyen de signaler que vous souhaitez voir plus de contenu de leur part.", - "onboard.how": "En attendant, vous pouvez cliquer sur les boutons de raccourci en haut pour voir ce que ce forum connaît d'autre et commencer à découvrir de nouveaux contenus !", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Trouver une catégorie..." + "category-search": "Trouver une catégorie...", + "see-more": "Voir plus", + "see-less": "Voir moins" } \ No newline at end of file diff --git a/public/language/gl/admin/advanced/jobs.json b/public/language/gl/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/gl/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/gl/admin/dashboard.json b/public/language/gl/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/gl/admin/dashboard.json +++ b/public/language/gl/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/gl/admin/manage/users.json b/public/language/gl/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/gl/admin/manage/users.json +++ b/public/language/gl/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/gl/admin/menu.json b/public/language/gl/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/gl/admin/menu.json +++ b/public/language/gl/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/gl/admin/settings/activitypub.json b/public/language/gl/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/gl/admin/settings/activitypub.json +++ b/public/language/gl/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/gl/admin/settings/general.json b/public/language/gl/admin/settings/general.json index 23438c4828..7a25eb12a4 100644 --- a/public/language/gl/admin/settings/general.json +++ b/public/language/gl/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/gl/error.json b/public/language/gl/error.json index 4292eaf10d..2d690b0593 100644 --- a/public/language/gl/error.json +++ b/public/language/gl/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Datos non válidos", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/gl/world.json b/public/language/gl/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/gl/world.json +++ b/public/language/gl/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/he/admin/advanced/jobs.json b/public/language/he/admin/advanced/jobs.json new file mode 100644 index 0000000000..5dcbe5bd7b --- /dev/null +++ b/public/language/he/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "משימות", + "job-name": "שם משימה", + "schedule": "לוח זמנים", + "next-run": "ריצה הבאה", + "last-duration": "זמן ביצוע אחרון", + "running": "בהרצה", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/he/admin/dashboard.json b/public/language/he/admin/dashboard.json index e57a4140a0..bc3d6e572d 100644 --- a/public/language/he/admin/dashboard.json +++ b/public/language/he/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "משתמשים חדשים", "posts": "פוסטים חדשים", "topics": "נושאים חדשים", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "פוסטים מרוחקים", + "remote-topics": "נושאים מרוחקים", + "messages": "הודעות", "page-views-seven": "ב-7 ימים אחרונים", "page-views-thirty": "ב-30 ימים אחרונים", "page-views-last-day": "ב-24 שעות אחרונות", - "page-views-custom": "טווח תאריכים מותאם אישית", + "page-views-custom": "טווח מותאם אישית", "page-views-custom-start": "תחילת טווח", "page-views-custom-end": "סוף טווח", "page-views-custom-help": "הכניסו טווח תאריכים של התקופה בה תרצו לצפות בתעבורת הפורום. הפורמט הנדרש הוא YYYY-MM-DD", diff --git a/public/language/he/admin/development/info.json b/public/language/he/admin/development/info.json index c661dbf942..3b59d685c1 100644 --- a/public/language/he/admin/development/info.json +++ b/public/language/he/admin/development/info.json @@ -8,7 +8,7 @@ "nodejs": "nodejs", "online": "מקוון", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "rss/heap בשימוש", "system-memory": "זיכרון מערכת", "used-memory-process": "זיכרון בשימוש ע\"י התהליך", "used-memory-os": "זיכרון מערכת בשימוש", diff --git a/public/language/he/admin/manage/categories.json b/public/language/he/admin/manage/categories.json index c139e95aa1..e666b0f26a 100644 --- a/public/language/he/admin/manage/categories.json +++ b/public/language/he/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "בחרו קטגוריה", "set-parent-category": "הגדרת קטגוריית אב", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "בסעיף זה ניתן להגדיר את הרשאות הגישה עבור חלקים באתר. ניתן להעניק הרשאות על בסיס משתמש או על בסיס קבוצה.", "privileges.category-selector": "הגדרת הרשאות עבור", "privileges.warning": "הערה: הגדרות ההרשאות נכנסות לתוקף באופן מיידי. אין צורך לשמור את הקטגוריה לאחר התאמת הגדרות אלה.", "privileges.section-viewing": "הרשאות צפייה", diff --git a/public/language/he/admin/manage/custom-reasons.json b/public/language/he/admin/manage/custom-reasons.json index 90a2e620af..a45a03b331 100644 --- a/public/language/he/admin/manage/custom-reasons.json +++ b/public/language/he/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "title": "ניהול סיבות מותאמות אישית", + "create-reason": "עריכת סיבה", + "edit-reason": "ערוך סיבה", + "reasons-help": "סיבות משמעותן רשימת הסברים מוגדרים מראש המשמשים בעת חסימה או השתקה של משתמשים, או בעת דחיית פוסטים בתור הפוסטים.", + "reason-title": "כותרת", + "reason-type": "סוג", + "reason-body": "תוכן", + "reason-all": "הכל", + "reason-ban": "הרחקה", + "reason-mute": "השתקה", + "reason-post-queue": "תור פוסטים", + "reason-type-help": "סוג הפעולה שסיבה זו חלה עליה. בחירה ב'הכל', תהפוך את הסיבה לזמינה עבור כל סוגי הפעולות", + "custom-reasons-saved": "סיבות מותאמות אישית נשמרו בהצלחה", + "delete-reason-confirm-x": "האם למחוק את הסיבה המותאמת אישית עם הכותרת %1?" } \ No newline at end of file diff --git a/public/language/he/admin/manage/privileges.json b/public/language/he/admin/manage/privileges.json index 48fa63ed41..5a54606411 100644 --- a/public/language/he/admin/manage/privileges.json +++ b/public/language/he/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "גישה לנושאים", "create-topics": "יצירת נושאים", "reply-to-topics": "תגובה לנושאים", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "שיוך נושאים לקטגוריות נוספות", "schedule-topics": "תזמון נושאים", "tag-topics": "תיוג נושאים", "edit-posts": "עריכת פוסטים", diff --git a/public/language/he/admin/manage/tags.json b/public/language/he/admin/manage/tags.json index 035cecb208..78b568dc02 100644 --- a/public/language/he/admin/manage/tags.json +++ b/public/language/he/admin/manage/tags.json @@ -7,7 +7,7 @@ "create": "יצירת תג", "add-tag": "הוספת תג", "modify": "שינוי תג", - "rename": "שנוי שם של תג", + "rename": "שינוי שם של תג", "delete": "מחיקת תגיות שנבחרו", "search": "חיפוש תג...", "settings": "הגדרות תגית", diff --git a/public/language/he/admin/manage/users.json b/public/language/he/admin/manage/users.json index 4c3dff4273..45f17924f0 100644 --- a/public/language/he/admin/manage/users.json +++ b/public/language/he/admin/manage/users.json @@ -23,7 +23,7 @@ "purge": "מחיקת משתמש(ים) ותוכן", "download-csv": "ייצוא משתמשים כ-CSV", "custom-user-fields": "שדות משתמש מותאמים אישית", - "custom-reasons": "Custom Reasons", + "custom-reasons": "סיבות מותאמות אישית", "manage-groups": "ניהול קבוצות", "set-reputation": "הגדרת מוניטין", "add-group": "הוספת קבוצה", @@ -40,6 +40,7 @@ "250-per-page": "250 לעמוד", "500-per-page": "500 לעמוד", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "לפי זהות משתמש (ID)", "search.uid-placeholder": "הזינו מזהה משתמש (ID) לחיפוש", "search.username": "לפי שם משתמש", @@ -64,7 +65,7 @@ "users.validation-pending": "ממתין לאימות", "users.validation-expired": "תוקף האימות פג", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "כתובות IP אחרונות", "users.postcount": "מספר פוסטים", "users.reputation": "מוניטין", "users.flags": "דיווחים", @@ -80,11 +81,11 @@ "temp-ban.length": "זמן הרחקה", "temp-ban.reason": "סיבה (אופציונאלי)", - "temp-ban.select-reason": "Select a reason", + "temp-ban.select-reason": "בחר סיבה", "temp-ban.hours": "שעות", "temp-ban.days": "ימים", "temp-ban.explanation": "הזינו זמן הרחקה. שימו לב הזנת מספר 0 מהווה הרחקה לצמיתות.", - "temp-mute.explanation": "Enter the length of time for the mute. Note that a time of 0 will be a considered a permanent mute.", + "temp-mute.explanation": "הזן את משך ההשתקה. שים לב שזמן 0 ייחשב כהשתקה לצמיתות.", "alerts.confirm-ban": "האם אתם רוצים להרחיק משתמש זה לצמיתות?", "alerts.confirm-ban-multi": "האם אתם רוצים להרחיק את המשתמשים לצמיתות?", diff --git a/public/language/he/admin/menu.json b/public/language/he/admin/menu.json index a78eaf272f..a8620b12e2 100644 --- a/public/language/he/admin/menu.json +++ b/public/language/he/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "%1 הגדרות", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "פדרציה", + "federation/general": "כללי", + "federation/content": "תוכן", + "federation/rules": "סיווג", + "federation/relays": "ממסרים", + "federation/pruning": "אחסון", + "federation/safety": "אמון ובטיחות", "section-appearance": "מראה חיצוני", "appearance/themes": "ערכות נושא", @@ -78,6 +78,7 @@ "advanced/logs": "לוג", "advanced/errors": "שגיאות", "advanced/cache": "עוגיות", + "advanced/jobs": "משימות", "development/logger": "ניהול לוג", "development/info": "מידע", diff --git a/public/language/he/admin/settings/activitypub.json b/public/language/he/admin/settings/activitypub.json index f5f07c9bf1..cf39104619 100644 --- a/public/language/he/admin/settings/activitypub.json +++ b/public/language/he/admin/settings/activitypub.json @@ -46,9 +46,10 @@ "server.filter-help-hostname": "הזן רק את שם המארח של המופע למטה (למשל.example.org), מופרדים עם מעברי שורות.", "server.filter-allow-list": "השתמשו בזה בתור רשימת אישורים במקום זאת", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "יוצאות", + "content.summary-limit": "מכסת תווים שמעבר לה ייווצר תקציר", + "content.summary-limit-help": "כאשר תוכן המופץ החוצה חורג ממכסת תווים זו, ייווצר תקצירהמורכב מכל המשפטים השלמים שלפני המגבלה. (ברירת מחדל: 500)", + "content.break-string": "מפריד הערת סיכום/מאמר", + "content.break-string-help": "משתמשים מתקדמים יכולים להזין את המפריד הזה ידנית בעת כתיבת נושאים חדשים. הוא מורה ל-NodeBB להשתמש בתוכן שעד לנקודה זו כחלק מה- תקציר . אם לא נעשה שימוש במחרוזת זו, תופעל חלופת ספירת התווים. (ברירת מחדל: [...] )", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/he/admin/settings/email.json b/public/language/he/admin/settings/email.json index df3fad9df1..2ecbe6f88b 100644 --- a/public/language/he/admin/settings/email.json +++ b/public/language/he/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "איחוד חיבורים מונע מ- NodeBB ליצור חיבור חדש לכל דואר אלקטרוני. אפשרות זו חלה רק אם SMTP תחבורה מופעלת.", "smtp-transport.allow-self-signed": "אפשר אישורים עם חתימה עצמית - self-signed", "smtp-transport.allow-self-signed-help": "הפעלת הגדרה זו תאפשר לכם להשתמש בתעודות TLS עם חתימה עצמית או לא חוקית.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "אימייל בדיקת SMTP נשלח בהצלחה.", "template": "עריכת תבנית דוא\"ל", "template.select": "בחירת תבנית דוא\"ל", "template.revert": "החזרה למקור", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "בדיקת הגדרות SMTP", "testing": "דוא\"ל בדיקה", - "testing.success": "Test Email Sent.", + "testing.success": "אימייל בדיקה נשלח.", "testing.select": "בחרו תבנית דוא\"ל", "testing.send": "שלח דוא\"ל בדיקה", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "‏\"%1\" ישמש לשליחת אימיילים לבדיקה.", + "testing.send-help-smtp": "תעבורת SMTP מופעלת ותשמש לשליחת אימיילים.", + "testing.send-help-no-plugin": "לא מותקן תוסף אימייל (emailer) לשליחת אימיילים, nodemailer ישמש כברירת מחדל.", + "testing.send-help": "אימייל הבדיקה יישלח לכתובת האימייל של המשתמש המחובר כעת, תוך שימוש בהגדרות השמורות בדף זה.", "subscriptions": "תקצירי דואר אלקטרוני", "subscriptions.disable": "הפיכת תקצירי דואר אלקטרוני ללא זמינים", "subscriptions.hour": "שעת תקציר", diff --git a/public/language/he/admin/settings/general.json b/public/language/he/admin/settings/general.json index 3d0cfbd4ba..1ab09d5bd4 100644 --- a/public/language/he/admin/settings/general.json +++ b/public/language/he/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "תיאור האתר", "keywords": "מילות מפתח של האתר", "keywords-placeholder": "מילות מפתח המתארות את הקהילה שלך, מופרדות באמצעות פסיקים", - "logo-and-icons": "לוגו אתר ואייקונים", + "logo-and-icons": "Media & Branding", "logo.image": "תמונה", "logo.image-placeholder": "נתב ללוגו שיראה בכותרת הפורום", "logo.upload": "העלאה", @@ -35,6 +35,8 @@ "touch-icon.help": "סמליל דף אינטרנט מופיע כאשר מישהו מסמן את דף האינטרנט שלך או מוסיף את דף האינטרנט שלך למסך הבית שלו, גודל ותבנית מומלצים: 512x512, תבנית PNG בלבד. אם לא הוגדר סמליל דף אינטרנט, NodeBB יחזור להשתמש בסמליל הפבאייקון.", "maskable-icon": "סמליל הניתן להסוואה (במסך הבית)", "maskable-icon.help": "סמליל הניתן להסוואה מופיע בדף הבית של הסוללרי, זהו תמונה אטומה עם מעט ריפוד שהיישום דף הבית שלך יוכל לחתוך אחר כך לצורה ולגודל הרצוי. עדיף לא להסתמך על צורה מסוימת, מכיוון שהצורה שנבחרה בסופו של דבר יכולה להשתנות לפי סוגי מסך בית ופלטפורמה. גודל ותבנית מומלצים: 512x512, תבנית PNG בלבד. אם לא הוגדר אייקון הניתן להסוואה, NodeBB יחזור להשתמש בסמליל דף האינטרנט.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "קישורים חיצוניים", "outgoing-links.warning-page": "שימוש בדף האזהרה לקישורים יוצאים", "search": "חיפוש", diff --git a/public/language/he/admin/settings/notifications.json b/public/language/he/admin/settings/notifications.json index 906bd1f819..0841faf04c 100644 --- a/public/language/he/admin/settings/notifications.json +++ b/public/language/he/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "קישור הודעת ברוכים הבאים", "welcome-notification-uid": "הודעת ברוכים הבאים למשתמש (UID)", "post-queue-notification-uid": "רשום משתמש בתור (UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "השהיה לשליחת התראות במייל (שניות)", + "notification-delay-help": "אם המשתמש יקרא את ההתראה בתוך פרק זמן זה, המייל לא יישלח.
ברירת מחדל: 60 שניות." } \ No newline at end of file diff --git a/public/language/he/admin/settings/uploads.json b/public/language/he/admin/settings/uploads.json index 59e3f786f8..eebfe41fb0 100644 --- a/public/language/he/admin/settings/uploads.json +++ b/public/language/he/admin/settings/uploads.json @@ -21,8 +21,8 @@ "reject-image-width-help": "תמונות רחבות יותר מערך זה יידחו.", "reject-image-height": "גובה תמונה מקסימלי (בפיקסלים)", "reject-image-height-help": "תמונות גבוהות יותר מערך זה יידחו", - "convert-pasted-images-to": "Convert pasted images to:", - "convert-pasted-images-to-default": "No Conversion (Keep Original Format)", + "convert-pasted-images-to": "המרת תמונות מודבקות ל:", + "convert-pasted-images-to-default": "ללא המרה (שמירה על הפורמט המקורי)", "convert-pasted-images-to-png": "PNG", "convert-pasted-images-to-jpeg": "JPEG", "convert-pasted-images-to-webp": "WebP", @@ -40,7 +40,7 @@ "default-avatar": "סמליל ברירת מחדל מותאמת אישית", "upload": "העלאה", "profile-image-dimension": "מימדי תמונות פרופיל", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(בפיקסלים, ברירת מחדל: 200 פיקסלים)", "max-profile-image-size": "גודל קובץ מקסימלי של תמונות פרופיל", "max-profile-image-size-help": "(בקיבי בייטים, ברירת מחדל: 256 KiB)", "max-cover-image-size": "גודל תמונת נושא מקסימלי", diff --git a/public/language/he/admin/settings/web-crawler.json b/public/language/he/admin/settings/web-crawler.json index c5be0cd295..cbac21a38a 100644 --- a/public/language/he/admin/settings/web-crawler.json +++ b/public/language/he/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "בטל הזנת RSS", "disable-sitemap-xml": "בטל את Sitemap.xml", "sitemap-topics": "מספר הנושאים להצגה במפת האתר", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "משך מטמון מפת אתר (שעות)", "clear-sitemap-cache": "נקה את זכרון מפת האתר", "view-sitemap": "צפייה במפת האתר" } \ No newline at end of file diff --git a/public/language/he/aria.json b/public/language/he/aria.json index d7102b1e5d..ce88375d19 100644 --- a/public/language/he/aria.json +++ b/public/language/he/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "צפיית משתמש בתגיות", "delete-upload-button": "כפתור מחיקת העלאה", "group-page-link-for": "%1 קבוצת דפים מקושרים ", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "הצגת נושאים משויכים" } \ No newline at end of file diff --git a/public/language/he/category.json b/public/language/he/category.json index 202c6ad2e2..ea27e91465 100644 --- a/public/language/he/category.json +++ b/public/language/he/category.json @@ -1,8 +1,8 @@ { "category": "קטגוריה", "subcategories": "קטגוריות משנה", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "עולם", + "uncategorized.description": "נושאים מחוץ לפורום הזה. הדעות המיוצגות כאן עשויות שלא לשקף את אלה של הפורום והחברים בו.", "handle.description": "ניתן לעקוב אחר קטגוריה זו מהאינטרנט החברתי הפתוח באמצעות הידית %1", "new-topic-button": "נושא חדש", "guest-login-post": "התחברו כדי לפרסם", diff --git a/public/language/he/error.json b/public/language/he/error.json index 6dff2a014c..65636047cf 100644 --- a/public/language/he/error.json +++ b/public/language/he/error.json @@ -1,5 +1,6 @@ { "invalid-data": "נתונים שגויים", + "invalid-config-field-value": "ערך לא תקין עבור שדה ההגדרה \"%1\": %2", "invalid-json": "אובייקט JSON לא תקין", "wrong-parameter-type": "ערך מסוג %3 היה צפוי למאפיין `%1`, אבל %2 התקבל במקום זאת", "required-parameters-missing": "פרמטרים נדרשים היו חסרים בקריאת API זו: %1", @@ -32,7 +33,7 @@ "invalid-path": "נתיב שגוי", "folder-exists": "התיקיה קיימת", "invalid-pagination-value": "ערך דף לא חוקי, חייב להיות לפחות %1 ולא מעל %2", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "ערך לא תקין עבור גבול הודעות שלא נקראו, חייב להיות לפחות 1 ולכל היותר %1", "username-taken": "שם משתמש תפוס", "email-taken": "כתובת האימייל כבר תפוסה.", "email-nochange": "כתובת דוא\"ל שהוזן זהה לדוא\"ל שנמצא כבר", @@ -253,7 +254,7 @@ "api.401": "לא נמצא סשן התחברות פעילה. נא התחברו ונסו שוב.", "api.403": "אינכם מורשים לבצע את החיוג", "api.404": "קריאת API שגויה", - "api.413": "The request payload is too large", + "api.413": "גוף הבקשה גדול מדי", "api.426": "HTTPS נדרש לבקשות ל-API של הכתיבה, אנא שלחו מחדש את בקשתכם באמצעות HTTPS", "api.429": "יותר מידי בקשות, אנא נסו שוב מאוחר יותר", "api.500": "שגיאה בלתי צפויה אירעה בעת ניסיון להגיש את בקשתכם.", diff --git a/public/language/he/global.json b/public/language/he/global.json index 7126099e43..f1e577818c 100644 --- a/public/language/he/global.json +++ b/public/language/he/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "פורמטי הקבצים המורשים הם %1", "unsaved-changes": "יש שינויים שלא נשמרו. האם אתם בטוחים שברצונכם להמשיך?", "reconnecting-message": "החיבור ל-%1 אבד, נא להמתין בזמן שאנו מנסים לחבר אתכם מחדש", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "התחבר מחדש אל %1 בהצלחה.", "play": "נגן", "cookies.message": "אתר זה משתמש ב cookies על מנת לשפר את חוויות המשתמש.", "cookies.accept": "קיבלתי!", diff --git a/public/language/he/groups.json b/public/language/he/groups.json index c2cedadc9b..e6a0bda7e9 100644 --- a/public/language/he/groups.json +++ b/public/language/he/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "קבוצה", "all-groups": "כל הקבוצות", "groups": "קבוצות", "members": "חברים", - "x-members": "%1 member(s)", + "x-members": "%1 חבר(ים)", "view-group": "הצגת קבוצה", "owner": "מנהל קבוצה", "new-group": "יצירת קבוצה חדשה", diff --git a/public/language/he/modules.json b/public/language/he/modules.json index 5783bdaf3b..f69d86ce19 100644 --- a/public/language/he/modules.json +++ b/public/language/he/modules.json @@ -82,7 +82,7 @@ "composer.hide-preview": "הסתרת תצוגה מקדימה", "composer.help": "עזרה", "composer.user-said-in": "%1 כתב ב%2:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [כתב](%2):", "composer.discard": "האם לבטל את השינויים שנעשו בפוסט זה?", "composer.submit-and-lock": "אשרו ונעלו", "composer.toggle-dropdown": "הצגת תפריט הנפתח", diff --git a/public/language/he/notifications.json b/public/language/he/notifications.json index ead4b477ad..0a54e6bacd 100644 --- a/public/language/he/notifications.json +++ b/public/language/he/notifications.json @@ -28,10 +28,10 @@ "new-messages-from": "%1 הודעות חדשות מאת %2", "new-message-in": "הודעה חדשה ב%1", "new-messages-in": "%1 הודעות חדשות ב%2", - "user-posted-in-public-room": "%1 wrote in %3", - "user-posted-in-public-room-dual": "%1 and %2 wrote in %4", - "user-posted-in-public-room-triple": "%1, %2 and %3 wrote in %5", - "user-posted-in-public-room-multiple": "%1, %2 and %3 others wrote in %5", + "user-posted-in-public-room": "‏ %1 כתב/ה ב- %3 ", + "user-posted-in-public-room-dual": "%1 ו %2 כתבו ב %4", + "user-posted-in-public-room-triple": "%1, %2 ו%3 כתבו ב %5", + "user-posted-in-public-room-multiple": "%1, %2 ו %3 אחרים כתבו ב %5", "upvoted-your-post-in": "%1 הצביע בעד הפוסט שלך %2", "upvoted-your-post-in-dual": "%1 ו%2 הצביעו בעד הפוסט שלך ב%3", "upvoted-your-post-in-triple": "%1, %2 ו%3 הצביעו בעד הפוסט שלך ב-%4.", @@ -50,13 +50,13 @@ "user-posted-to-dual": "%1 ו%2 הגיבו ל: %3", "user-posted-to-triple": "%1, %2 ו%3 הגיבו ל: %4", "user-posted-to-multiple": "%1, %2 ו-%3 אחרים הגיבו ל: %4", - "user-posted-topic": "%1 posted %2", - "user-edited-post": "%1 edited a post in %2", - "user-posted-topic-with-tag": "%1 posted %2 (tagged %3)", - "user-posted-topic-with-tag-dual": "%1 posted %2 (tagged %3 and %4)", - "user-posted-topic-with-tag-triple": "%1 posted %2 (tagged %3, %4, and %5)", - "user-posted-topic-with-tag-multiple": "%1 posted %2 (tagged %3)", - "user-posted-topic-in-category": "%1 posted %2 in %3", + "user-posted-topic": "%1 פרסם/ה %2", + "user-edited-post": "%1 ערך פוסט ב %2", + "user-posted-topic-with-tag": "%1 פרסם/ה %2 (מתוייג ב %3)", + "user-posted-topic-with-tag-dual": "%1 פרסם/ה %2 (מתוייג ב %3 ו %4)", + "user-posted-topic-with-tag-triple": "%1 פרסמ/ה %2 (מתוייג ב %3, %4, ו %5)", + "user-posted-topic-with-tag-multiple": "%1 פרסם/ה %2 (מתוייג ב %3)", + "user-posted-topic-in-category": "%1 פרסם/ה %2 in %3", "user-started-following-you": "%1 התחיל לעקוב אחריך.", "user-started-following-you-dual": "%1 ו-%2 התחילו לעקוב אחריך.", "user-started-following-you-triple": "%1, %2 ו%3 התחילו לעקוב אחריך.", @@ -65,15 +65,15 @@ "new-register-multiple": "ישנן %1 בקשות הרשמה שמחכות לבדיקה.", "flag-assigned-to-you": "דיווח %1 הוקצה עבורך", "post-awaiting-review": "הפוסט ממתין לאישור", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "נושא ממתין לבדיקה", "profile-exported": "%1 פרופיל יוצא, לחץ כדי להוריד.", "posts-exported": "%1 פוסטים יוצאו, לחץ כדי להוריד.", "uploads-exported": "%1 העלאות יוצאו, לחץ כדי להוריד.", "users-csv-exported": "משתמשים יוצאו כ-csv, לחץ כאן להורדה.", "post-queue-accepted": "הפוסט ששלחת התקבל. לחץ כאן כדי לראות את הפוסט", "post-queue-rejected": "הפוסט ששלחת נדחה", - "post-queue-rejected-for-reason": "Your queued post has been rejected for the following reason: \"%1\"", - "post-queue-notify": "Queued post received a notification: \"%1\"", + "post-queue-rejected-for-reason": "הפוסט הממתין שלך נדחה מהסיבה הבאה: \"%1\"", + "post-queue-notify": "פוסט ממתין קיבל התראה: \"%1\"", "email-confirmed": "כתובת המייל אושרה", "email-confirmed-message": "תודה שאישרת את כתובת המייל שלך. החשבון שלך פעיל כעת.", "email-confirm-error-message": "אירעה שגיאה בעת אישור המייל שלך. ייתכן כי הקוד היה שגוי או פג תוקף.", @@ -85,16 +85,16 @@ "notificationType-upvote": "כשמישהו מצביע בעד הפוסט שלך", "notificationType-new-topic": "כשמישהו שאתם עוקבים אחריו פרסם נושא", "notificationType-new-topic-with-tag": "כשנושא מתפרסם עם תג שאתם עוקבים אחריו", - "notificationType-new-topic-in-category": "When a topic is posted in a watched category", - "notificationType-new-reply": "When a reply is posted in a watched topic", - "notificationType-post-edit": "When a post is edited in a watched topic", + "notificationType-new-topic-in-category": "כאשר מפורסם נושא בקטגוריה שבמעקב", + "notificationType-new-reply": "כאשר מפורסמת תגובה בנושא שבמעקב", + "notificationType-post-edit": "כאשר פוסט נערך בנושא שאתם עוקבים אחריו", "notificationType-follow": "כשמישהו מתחיל לעקוב אחריך", "notificationType-new-chat": "כשאתם מקבלים הודעת צאט", "notificationType-new-group-chat": "כשאתם מקבלים הודעת צ'אט קבוצתית", "notificationType-new-public-chat": "כאשר מתקבלת הודעה בקבוצת צ'אט ציבורית", "notificationType-group-invite": "כשאתם מקבלים הזמנה מקבוצה", "notificationType-group-leave": "כשמשתמש עוזב את הקבוצה שלכם", - "notificationType-group-request-membership": "When a user requests to join a group you own", + "notificationType-group-request-membership": "כאשר משתמש מבקש להצטרף לקבוצה שבבעלותך", "notificationType-new-register": "כשמישהו מתווסף לתור הרישום", "notificationType-post-queue": "כשפוסט חדש נכנס לתור", "notificationType-new-post-flag": "כשמדווחים על פוסט", diff --git a/public/language/he/social.json b/public/language/he/social.json index a08072bc9a..7245261387 100644 --- a/public/language/he/social.json +++ b/public/language/he/social.json @@ -1,14 +1,14 @@ { - "sign-in-with-twitter": "היכנס באמצעות Twitter", - "sign-up-with-twitter": "הירשם באמצעות Twitter", - "sign-in-with-github": "היכנס באמצעות Github", - "sign-up-with-github": "הירשם באמצעות Github", - "sign-in-with-google": "היכנס באמצעות Google", - "sign-up-with-google": "הירשם באמצעות Google", - "log-in-with-facebook": "היכנס באמצעות Facebook", - "continue-with-facebook": "המשך בFacebook", - "sign-in-with-linkedin": "היכנס באמצעות LinkedIn", - "sign-up-with-linkedin": "הירשם באמצעות LinkedIn", - "sign-in-with-wordpress": "Sign in with WordPress", - "sign-up-with-wordpress": "Sign up with WordPress" + "sign-in-with-twitter": "כניסה באמצעות Twitter", + "sign-up-with-twitter": "הרשמה באמצעות Twitter", + "sign-in-with-github": "כניסה באמצעות Github", + "sign-up-with-github": "הרשמה באמצעות Github", + "sign-in-with-google": "כניסה באמצעות Google", + "sign-up-with-google": "הרשמה באמצעות Google", + "log-in-with-facebook": "כניסה באמצעות Facebook", + "continue-with-facebook": "המשך עם Facebook", + "sign-in-with-linkedin": "כניסה באמצעות LinkedIn", + "sign-up-with-linkedin": "הרשמה באמצעות LinkedIn", + "sign-in-with-wordpress": "כניסה באמצעות וורדפרס", + "sign-up-with-wordpress": "הרשמה באמצעות וורדפרס" } \ No newline at end of file diff --git a/public/language/he/themes/harmony.json b/public/language/he/themes/harmony.json index bc4ad16264..92f9b6cf23 100644 --- a/public/language/he/themes/harmony.json +++ b/public/language/he/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "ערכת נושא Harmony", "skins": "עיצובים", - "light": "Light", - "dark": "Dark", + "light": "בהיר", + "dark": "כהה", "collapse": "כיווץ", "expand": "הרחבה", "sidebar-toggle": "הצגת סרגל צד", diff --git a/public/language/he/topic.json b/public/language/he/topic.json index e2771916e1..393046d12e 100644 --- a/public/language/he/topic.json +++ b/public/language/he/topic.json @@ -69,8 +69,8 @@ "user-referenced-topic-on": "%1 התייחס לנושא זה ב%3", "user-forked-topic-ago": "%1 פיצל נושא זה %3", "user-forked-topic-on": "%1 פיצל נושא זה ב%3", - "user-crossposted-topic-ago": "%1 crossposted this topic to %2 %3", - "user-crossposted-topic-on": "%1 crossposted this topicto %2 on %3", + "user-crossposted-topic-ago": "%1 פרסם את הנושא הזה בפרסום צולב ב-%2 %3", + "user-crossposted-topic-on": "%1 פרסם את הנושא הזה בפרסום צולב ב-%2 ב-%3", "bookmark-instructions": "לחצו כאן כדי לחזור לפוסט האחרון שקראתם בנושא זה.", "flag-post": "דיווח על פוסט זה", "flag-user": "דיווח על משתמש זה", @@ -182,7 +182,7 @@ "composer.replying-to": "תגובה ל%1", "composer.new-topic": "נושא חדש", "composer.editing-in": "עריכת פוסט ב-%1", - "composer.untitled-topic": "Untitled Topic", + "composer.untitled-topic": "נושא ללא כותרת", "composer.uploading": "מעלה...", "composer.thumb-url-label": "הדביקו את כתובת ה-URL לתמונה הממוזערת עבור הנושא", "composer.thumb-title": "הוספת תמונה ממוזערת לנושא", @@ -225,7 +225,7 @@ "no-more-next-post": "אין לכם יותר פוסטים בנושא זה", "open-composer": "פתיחת העורך", "post-quick-reply": "תגובה מהירה", - "post-quick-create": "Quick post", + "post-quick-create": "פוסט מהיר", "navigator.index": "פוסט %1 מתוך %2", "navigator.unread": "%1 לא נקראו", "upvote-post": "הצבעה לפוסט", @@ -235,7 +235,7 @@ "thumb-image": "תמונה ממוזערת של נושא", "announcers": "שיתופים", "announcers-x": "שיתופים (%1)", - "guest-cta.title": "Hello! It looks like you're interested in this conversation, but you don't have an account yet.", - "guest-cta.message": "Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.", - "guest-cta.closing": "With your input, this post could be even better 💗" + "guest-cta.title": "שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.", + "guest-cta.message": "נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.", + "guest-cta.closing": "בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗" } \ No newline at end of file diff --git a/public/language/he/user.json b/public/language/he/user.json index 41005b91a2..e52dc0a9fa 100644 --- a/public/language/he/user.json +++ b/public/language/he/user.json @@ -105,7 +105,7 @@ "show-email": "הצגת כתובת האימייל שלי", "show-fullname": "הצגת שמי המלא", "restrict-chats": "אפשר רק הודעות צ'אט ממשתמשים שאני עוקב אחריהם", - "disable-incoming-chats": "Disable incoming chat messages ", + "disable-incoming-chats": "השבתת הודעות צ'אט נכנסות ", "chat-allow-list": "אפשור הודעות צ'אט מהמשתמשים הבאים", "chat-deny-list": "דחיית הודעות צ'אט מהמשתמשים הבאים", "chat-list-add-user": "הוספת משתמש", @@ -132,8 +132,8 @@ "email-hidden": "כתובת אימייל מוסתרת", "hidden": "מוסתר", "paginate-description": "הצגת נושאים ופוסטים בעמודים במקום כרשימת גלילה אין-סופית", - "topics-per-page": "Topics per page", - "posts-per-page": "Posts per page", + "topics-per-page": "נושאים לכל עמוד", + "posts-per-page": "פוסטים לכל עמוד", "category-topic-sort": "מיון נושאים בקטגוריה", "topic-post-sort": "מיון פוסטים בנושא", "max-items-per-page": "מקסימום %1", @@ -146,11 +146,11 @@ "upvote-notif-freq.threshold": "ב-1, 5, 10, 25, 50, 100, 150, 200...", "upvote-notif-freq.logarithmic": "ב-10, 100, 1000...", "upvote-notif-freq.disabled": "מושבת", - "notification-type-web": "Web", - "notification-type-email": "Email", + "notification-type-web": "אינטרנט", + "notification-type-email": "אימייל", "browsing": "הגדרות ניווט", - "unread.cutoff": "Unread cutoff (Maximum %1 days)", - "unread.cutoff-help": "Topics will be marked read if they have not been updated within this number of days.", + "unread.cutoff": "גבול הודעות שלא נקראו (מקסימום %1 ימים)", + "unread.cutoff-help": "נושאים יסומנו כנקראו אם לא עודכנו בתוך מספר הימים הזה.", "open-links-in-new-tab": "פתיחת קישורים חיצוניים בכרטיסייה חדשה", "enable-topic-searching": "הפעלת חיפוש בתוך נושא", "topic-search-help": "החיפוש בתוך הנושא יעקוף את שיטת החיפוש של הדפדפן, ויאפשר לכם לחפש בכל הנושא - ולא רק במה שמוצג על המסך, עם זאת בלחיצה נוספת על Ctrl+F ייפתח לכם החיפוש הרגיל של הדפדפן", @@ -179,7 +179,7 @@ "sso.dissociate": "ביטול שיוך", "sso.dissociate-confirm-title": "אישור ביטול שיוך", "sso.dissociate-confirm": "האם לבטל שיוך חשבונכם מ%1?", - "info.invited-by": "Invited by", + "info.invited-by": "הוזמן ע\"י", "info.latest-flags": "דיווחים אחרונים", "info.profile": "פרופיל", "info.post": "פוסט", diff --git a/public/language/he/world.json b/public/language/he/world.json index 60f61b84c4..ace8b5cad4 100644 --- a/public/language/he/world.json +++ b/public/language/he/world.json @@ -1,12 +1,14 @@ { "name": "עולם", "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", - "recent": "All", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", + "popular-day": "פופולרי (יומי)", + "popular-week": "פופולרי (שבועי)", + "popular-month": "פופולרי (חודשי)", + "popular-year": "פופולרי (שנתי)", + "popular-alltime": "פופולרי (כל הזמן)", + "recent": "הכל", "help": "עזרה", "help.title": "מה זה העמוד הזה?", @@ -16,10 +18,12 @@ "help.federating": "באופן דומה, אם משתמשים מחוץ לפורום זה מתחילים לעקוב אחריכם, אז הפוסטים שלכם יתחילו להופיע גם באפליקציות ובאתרים אלה.", "help.next-generation": "זהו הדור הבא של המדיה החברתית, התחלו לתרום עוד היום!", - "onboard.title": "החלון שלכם אל ה-fediverse...", - "onboard.what": "זוהי הקטגוריה המותאמת אישית שלכם המורכבת רק מתוכן שנמצא מחוץ לפורום זה. אם משהו מופיע בדף הזה תלוי אם אתם עוקבים אחריו, או אם הפוסט הזה שותף על ידי מישהו שאתם עוקבים אחריו.", - "onboard.why": "יש הרבה דברים שקורים מחוץ לפורום הזה, ולא כל זה רלוונטי לתחומי העניין שלכם. לכן מעקב אחר אנשים הוא הדרך הטובה ביותר לאותת שאתם רוצים לראות יותר ממישהו אחר.", - "onboard.how": "בינתיים, תוכלו ללחוץ על כפתורי הקיצור בחלק העליון כדי לראות על מה עוד הפורום הזה יודע, ולהתחיל לגלות תוכן חדש!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "מצא קטגוריה...", + "see-more": "ראה עוד", + "see-less": "ראה פחות" } \ No newline at end of file diff --git a/public/language/hr/admin/advanced/jobs.json b/public/language/hr/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/hr/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/hr/admin/dashboard.json b/public/language/hr/admin/dashboard.json index 7877e34741..defff9b76f 100644 --- a/public/language/hr/admin/dashboard.json +++ b/public/language/hr/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Teme", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/hr/admin/manage/users.json b/public/language/hr/admin/manage/users.json index 35ffbc47f8..5ca2530c2d 100644 --- a/public/language/hr/admin/manage/users.json +++ b/public/language/hr/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "Po korisničkom imenu", diff --git a/public/language/hr/admin/menu.json b/public/language/hr/admin/menu.json index 11c33be756..5ba56028d2 100644 --- a/public/language/hr/admin/menu.json +++ b/public/language/hr/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Dnevnik", "advanced/errors": "Greške", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Dnevnik", "development/info": "Info", diff --git a/public/language/hr/admin/settings/activitypub.json b/public/language/hr/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/hr/admin/settings/activitypub.json +++ b/public/language/hr/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/hr/admin/settings/general.json b/public/language/hr/admin/settings/general.json index d21861149a..72f42c022c 100644 --- a/public/language/hr/admin/settings/general.json +++ b/public/language/hr/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Ključne riječi", "keywords-placeholder": "Ključne riječi koje opisuju Vašu zajednicu, odvojeni zarezom", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Slika", "logo.image-placeholder": "Putanja logotipa za zaglavlje foruma", "logo.upload": "Učitaj", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Odlazne poveznice", "outgoing-links.warning-page": "Koristi upozorenje za odlazne poveznice", "search": "Search", diff --git a/public/language/hr/error.json b/public/language/hr/error.json index 93cceebc5b..aedaf363ea 100644 --- a/public/language/hr/error.json +++ b/public/language/hr/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Nevažeći podaci", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/hr/world.json b/public/language/hr/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/hr/world.json +++ b/public/language/hr/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/hu/admin/advanced/jobs.json b/public/language/hu/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/hu/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/hu/admin/dashboard.json b/public/language/hu/admin/dashboard.json index 6c2b58563a..3cdcae1005 100644 --- a/public/language/hu/admin/dashboard.json +++ b/public/language/hu/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Témakörök", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Az utóbbi 7 napban", "page-views-thirty": "Az utóbbi 30 napban", "page-views-last-day": "Az utóbbi 24 órában", - "page-views-custom": "Egyéni dátum tartomány", + "page-views-custom": "Custom Range", "page-views-custom-start": "Tartomény kezdete", "page-views-custom-end": "Tartomány vége", "page-views-custom-help": "Adj meg egy dátum tartományt a kívánt oldal megtekintések megtekintéséhez. Ha nem áll rendelkezésre dátumválasztó, az elfogadott formátum ÉÉÉÉ-HH-NN", diff --git a/public/language/hu/admin/manage/users.json b/public/language/hu/admin/manage/users.json index b98972180b..ebb3f7c73b 100644 --- a/public/language/hu/admin/manage/users.json +++ b/public/language/hu/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 oldalanként", "500-per-page": "500 oldalanként", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Azonosító alapján", "search.uid-placeholder": "Írj be egy azonosítót a kereséshez", "search.username": "Felhasználónév szerint", diff --git a/public/language/hu/admin/menu.json b/public/language/hu/admin/menu.json index 46ccaadcad..dcd0be4653 100644 --- a/public/language/hu/admin/menu.json +++ b/public/language/hu/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Naplók", "advanced/errors": "Hibák", "advanced/cache": "Gyorsítótár", + "advanced/jobs": "Jobs", "development/logger": "Naplózó", "development/info": "Információ", diff --git a/public/language/hu/admin/settings/activitypub.json b/public/language/hu/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/hu/admin/settings/activitypub.json +++ b/public/language/hu/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/hu/admin/settings/general.json b/public/language/hu/admin/settings/general.json index 29839979b5..eb71f531b7 100644 --- a/public/language/hu/admin/settings/general.json +++ b/public/language/hu/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Weboldal kulcsszavak", "keywords-placeholder": "A közösségedet leíró kulcsszavak, vesszővel elválasztva", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Kép", "logo.image-placeholder": "A logó elérési útvonala, amit a fórum fejlécében fogunk megjeleníteni", "logo.upload": "Feltöltés", @@ -35,6 +35,8 @@ "touch-icon.help": "Ajánlott méret és formátum: 512x512, csak PNG formátum. Ha nincs beállítva, a NodeBB a favicon-t fogja használni.", "maskable-icon": "Maszkolható (főképernyő) ikon", "maskable-icon.help": "Ajánlott méret és formátum: 512x512, csak PNG formátum. Ha nincs beállítva, a NodeBB a favicon-t fogja használni", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Kimenő linkek", "outgoing-links.warning-page": "Kimenő link figyelmeztető oldal használata", "search": "Keresés", diff --git a/public/language/hu/error.json b/public/language/hu/error.json index 6a0e6c5564..46bf267a06 100644 --- a/public/language/hu/error.json +++ b/public/language/hu/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Érvénytelen adat", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Érvénytelen JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/hu/world.json b/public/language/hu/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/hu/world.json +++ b/public/language/hu/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/hy/admin/advanced/jobs.json b/public/language/hy/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/hy/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/hy/admin/dashboard.json b/public/language/hy/admin/dashboard.json index 370b5cf6ec..3241ddd457 100644 --- a/public/language/hy/admin/dashboard.json +++ b/public/language/hy/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Թեմաներ", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Վերջին 7 օրը", "page-views-thirty": "Վերջին 30 օրը", "page-views-last-day": "Վերջին 24 ժամը", - "page-views-custom": "Հատուկ ամսաթվերի միջակայք", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Միջակայքի վերջ", "page-views-custom-help": "Մուտքագրեք էջի դիտումների ամսաթվերի միջակայքը, որը ցանկանում եք դիտել: Եթե ամսաթվերի ընտրիչ չկա, ապա ընդունված ձևաչափն է՝ ՏՏՏՏ-ԱՄ-ՕՕ", diff --git a/public/language/hy/admin/manage/users.json b/public/language/hy/admin/manage/users.json index 7f80772825..ea1fe5df8b 100644 --- a/public/language/hy/admin/manage/users.json +++ b/public/language/hy/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 մեկ էջի համար", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Օգտատիրոջ ID-ով", "search.uid-placeholder": "Որոնման համար մուտքագրեք օգտվողի ID", "search.username": "Ըստ օգտատիրոջ անվան ", diff --git a/public/language/hy/admin/menu.json b/public/language/hy/admin/menu.json index 427930f66c..3ca815635b 100644 --- a/public/language/hy/admin/menu.json +++ b/public/language/hy/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Մատյաններ", "advanced/errors": "Սխալներ ", "advanced/cache": "Քեշ", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Տեղեկատվություն", diff --git a/public/language/hy/admin/settings/activitypub.json b/public/language/hy/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/hy/admin/settings/activitypub.json +++ b/public/language/hy/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/hy/admin/settings/general.json b/public/language/hy/admin/settings/general.json index ba5240156d..d42a299463 100644 --- a/public/language/hy/admin/settings/general.json +++ b/public/language/hy/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Կայքի հիմնաբառեր", "keywords-placeholder": "Ձեր համայնքը նկարագրող հիմնաբառեր՝ բաժանված ստորակետերով", - "logo-and-icons": "Կայքի Լոգո և պատկերանշաններ", + "logo-and-icons": "Media & Branding", "logo.image": "Նկար ", "logo.image-placeholder": "Ճանապարհ դեպի լոգո՝ ֆորումի վերնագրում ցուցադրելու համար", "logo.upload": "Վերբեռնել", @@ -35,6 +35,8 @@ "touch-icon.help": "Առաջարկվող չափը և ձևաչափը՝ 512x512, միայն PNG ձևաչափ: Եթե որևէ հպման պատկերակ նշված չէ, NodeBB-ը կվերադառնա ֆավիկոնի օգտագործմանը:", "maskable-icon": "Դիմակելի (հիմնական էկրան) պատկերակ", "maskable-icon.help": "Առաջարկվող չափը և ձևաչափը՝ 512x512, միայն PNG ձևաչափ: Եթե ոչ մի դիմակավոր պատկերակ նշված չէ, NodeBB-ը կվերադառնա Touch Icon-ին:", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Ելքային հղումներ", "outgoing-links.warning-page": "Օգտագործեք ելքային հղումների նախազգուշացման էջը", "search": "Որոնում", diff --git a/public/language/hy/error.json b/public/language/hy/error.json index 2be8ec964f..624c261244 100644 --- a/public/language/hy/error.json +++ b/public/language/hy/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Սխալ տվյալ", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Անվավեր JSON", "wrong-parameter-type": "«%1» հատկության համար սպասվում էր %3 տիպի արժեք, բայց փոխարենը ստացվեց %2", "required-parameters-missing": "Պահանջվող պարամետրերը բացակայում էին այս API զանգից՝ %1", diff --git a/public/language/hy/world.json b/public/language/hy/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/hy/world.json +++ b/public/language/hy/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/id/admin/advanced/jobs.json b/public/language/id/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/id/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/id/admin/dashboard.json b/public/language/id/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/id/admin/dashboard.json +++ b/public/language/id/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/id/admin/manage/users.json b/public/language/id/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/id/admin/manage/users.json +++ b/public/language/id/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/id/admin/menu.json b/public/language/id/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/id/admin/menu.json +++ b/public/language/id/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/id/admin/settings/activitypub.json b/public/language/id/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/id/admin/settings/activitypub.json +++ b/public/language/id/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/id/admin/settings/general.json b/public/language/id/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/id/admin/settings/general.json +++ b/public/language/id/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/id/error.json b/public/language/id/error.json index 1ae569cedd..c1fa0a7ab4 100644 --- a/public/language/id/error.json +++ b/public/language/id/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Data Salah", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/id/world.json b/public/language/id/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/id/world.json +++ b/public/language/id/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/it/admin/advanced/jobs.json b/public/language/it/admin/advanced/jobs.json new file mode 100644 index 0000000000..110381511f --- /dev/null +++ b/public/language/it/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Lavori", + "job-name": "Nome del lavoro", + "schedule": "Programma", + "next-run": "Prossima esecuzione", + "last-duration": "Ultima durata", + "running": "In esecuzione", + "active": "Attivo" +} \ No newline at end of file diff --git a/public/language/it/admin/dashboard.json b/public/language/it/admin/dashboard.json index a4c28cf9e8..1b2c43965b 100644 --- a/public/language/it/admin/dashboard.json +++ b/public/language/it/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "Nuovi utenti", "posts": "Post", "topics": "Discussioni", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "Post remoti", + "remote-topics": "Discussioni remote", + "messages": "Messaggi", "page-views-seven": "Ultimi 7 giorni", "page-views-thirty": "Ultimi 30 giorni", "page-views-last-day": "Ultime 24 ore", - "page-views-custom": "Intervallo data personalizzato", + "page-views-custom": "Intervallo personalizzato", "page-views-custom-start": "Inizio intervallo", "page-views-custom-end": "Fine intervallo", "page-views-custom-help": "Immettere un intervallo di date, delle pagine viste, che si desidera visualizzare. Se non è disponibile un selezionatore di date, il formato accettato è il seguente YYYY-MM-DD", diff --git a/public/language/it/admin/development/info.json b/public/language/it/admin/development/info.json index 56d9093d24..ddf000d4a2 100644 --- a/public/language/it/admin/development/info.json +++ b/public/language/it/admin/development/info.json @@ -8,7 +8,7 @@ "nodejs": "nodejs", "online": "online", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "rss/heap utilizzato", "system-memory": "memoria di sistema", "used-memory-process": "Memoria usata dal processo", "used-memory-os": "Memoria di sistema usata", diff --git a/public/language/it/admin/manage/categories.json b/public/language/it/admin/manage/categories.json index 1011daa94e..b59a2a1b8c 100644 --- a/public/language/it/admin/manage/categories.json +++ b/public/language/it/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "Seleziona Categoria", "set-parent-category": "Imposta la Categoria Padre", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "In questa sezione è possibile configurare i privilegi di controllo degli accessi per alcune parti del sito. I privilegi possono essere concessi per singolo utente o per gruppo.", "privileges.category-selector": "Configura privilegi per", "privileges.warning": "Nota: Le impostazioni dei privilegi hanno effetto immediato. Non è necessario salvare la categoria dopo aver regolato queste impostazioni.", "privileges.section-viewing": "Visualizzazione dei Privilegi", diff --git a/public/language/it/admin/manage/custom-reasons.json b/public/language/it/admin/manage/custom-reasons.json index 90a2e620af..eb7214608a 100644 --- a/public/language/it/admin/manage/custom-reasons.json +++ b/public/language/it/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", + "title": "Gestisci motivi personalizzati", + "create-reason": "Crea motivo", + "edit-reason": "Modifica motivo", + "reasons-help": "Le motivazioni sono spiegazioni predefinite utilizzate quando si bannano o si silenziano gli utenti, o quando si rifiutano i post nella coda dei post.", + "reason-title": "Titolo", + "reason-type": "Tipo", + "reason-body": "Corpo", + "reason-all": "Tutto", "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "reason-mute": "Silenzioso", + "reason-post-queue": "Coda post", + "reason-type-help": "Il tipo di azione a cui si applica questo motivo. Se si seleziona \"Tutti\", questo motivo sarà disponibile per tutti i tipi di azione.", + "custom-reasons-saved": "Motivi personalizzati salvati con successo", + "delete-reason-confirm-x": "Sei sicuro di voler eliminare il motivo personalizzato con il titolo %1?" } \ No newline at end of file diff --git a/public/language/it/admin/manage/privileges.json b/public/language/it/admin/manage/privileges.json index fb5498ffc0..93b96233dc 100644 --- a/public/language/it/admin/manage/privileges.json +++ b/public/language/it/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "Accesso discussioni", "create-topics": "Crea discussioni", "reply-to-topics": "Risposta alle discussioni", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "Discussioni postate più volte", "schedule-topics": "Pianificazione discussioni", "tag-topics": "Tag discussioni", "edit-posts": "Modifica i post", diff --git a/public/language/it/admin/manage/users.json b/public/language/it/admin/manage/users.json index 193896c0fe..3c00762d4f 100644 --- a/public/language/it/admin/manage/users.json +++ b/public/language/it/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per pagina", "500-per-page": "500 per pagina", + "search.help": "Usa "*" per effettuare ricerche parziali, ad esempio "*richiesta"", "search.uid": "Da ID Utente", "search.uid-placeholder": "Inserisci l'ID utente da cercare", "search.username": "Da Nome Utente", @@ -55,7 +56,7 @@ "inactive.12-months": "12 Mesi", "users.uid": "id utente", - "users.user-id": "User ID", + "users.user-id": "ID utente", "users.username": "username", "users.email": "email", "users.no-email": "(nessuna email)", @@ -64,7 +65,7 @@ "users.validation-pending": "Validazione in sospeso", "users.validation-expired": "Convalida scaduta", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "IP recenti", "users.postcount": "numero di post", "users.reputation": "reputazione", "users.flags": "segnalazioni", diff --git a/public/language/it/admin/menu.json b/public/language/it/admin/menu.json index 88b0486c2e..a5a1f36227 100644 --- a/public/language/it/admin/menu.json +++ b/public/language/it/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "%1 Impostazioni", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "Federazione", + "federation/general": "Generale", + "federation/content": "Contenuto", + "federation/rules": "Categorizzazione", + "federation/relays": "Relè", + "federation/pruning": "Archiviazione", + "federation/safety": "Fiducia e sicurezza", "section-appearance": "Stile", "appearance/themes": "Themi", @@ -78,6 +78,7 @@ "advanced/logs": "Registri", "advanced/errors": "Errori", "advanced/cache": "Cache", + "advanced/jobs": "Lavori", "development/logger": "Registratore", "development/info": "Informazioni", diff --git a/public/language/it/admin/settings/activitypub.json b/public/language/it/admin/settings/activitypub.json index faa6f19ccb..320400e725 100644 --- a/public/language/it/admin/settings/activitypub.json +++ b/public/language/it/admin/settings/activitypub.json @@ -46,9 +46,10 @@ "server.filter-help-hostname": "Inserisci solo il nome host dell'istanza sottostante (ad es. example.org), separato da interruzioni di riga.", "server.filter-allow-list": "Usa invece questo come Elenco permessi", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "In uscita", + "content.summary-limit": "Numero di caratteri dopo il quale sarà generato un riepilogo", + "content.summary-limit-help": "Quando il contenuto federato supera questo limite di caratteri, sarà generato un riepilogo che comprende tutte le frasi complete precedenti a tale limite. (Predefinito: 500)\n ", + "content.break-string": "Delimitatore di nota/articolo", + "content.break-string-help": "Questo delimitatore può essere inserito manualmente dagli utenti esperti durante la composizione di nuove discussioni. Indica a NodeBB di usare il contenuto fino a quel punto come parte del riepilogo. Se questa stringa non viene usata, si applica il conteggio dei caratteri di riserva. (Predefinito: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/it/admin/settings/email.json b/public/language/it/admin/settings/email.json index e4f3dc88cd..36142cf066 100644 --- a/public/language/it/admin/settings/email.json +++ b/public/language/it/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "Il pooling delle connessioni impedisce a NodeBB di creare una nuova connessione per ogni email. Questa opzione si applica solo se è abilitato il trasporto SMTP.", "smtp-transport.allow-self-signed": "Consenti certificati autofirmati", "smtp-transport.allow-self-signed-help": "L'attivazione di questa impostazione consente di utilizzare certificati TLS autofirmati o non validi.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "Email di test SMTP inviata con successo.", "template": "Modifica Modello Email", "template.select": "Seleziona Modello Email", "template.revert": "Torna all'originale", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "Test impostazioni SMTP", "testing": "Prova Email", - "testing.success": "Test Email Sent.", + "testing.success": "Email di test inviata.", "testing.select": "Seleziona Modello Email", "testing.send": "Invia Email di prova", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" sarà utilizzato per inviare email di test.", + "testing.send-help-smtp": "Il trasporto SMTP è abilitato e sarà utilizzato per inviare email.", + "testing.send-help-no-plugin": "Non è installato alcun plugin per l'invio di email, nodemailer sarà utilizzato per impostazione predefinita.", + "testing.send-help": "L'email di test sarà inviata all'indirizzo email dell'utente attualmente connesso utilizzando le impostazioni salvate in questa pagina. ", "subscriptions": "Email riepilogo", "subscriptions.disable": "Disabilita email riepilogo", "subscriptions.hour": "Orario riepilogo", diff --git a/public/language/it/admin/settings/general.json b/public/language/it/admin/settings/general.json index 6b1fea08ae..ebb00fe63f 100644 --- a/public/language/it/admin/settings/general.json +++ b/public/language/it/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Descrizione sito", "keywords": "Parole chiave del sito", "keywords-placeholder": "Parole chiave che descrivono la vostra comunità, separate da virgole", - "logo-and-icons": "Logo e icone del sito", + "logo-and-icons": "Media & Branding", "logo.image": "Immagine", "logo.image-placeholder": "Percorso del logo da visualizzare sull'intestazione del forum", "logo.upload": "Carica", @@ -35,6 +35,8 @@ "touch-icon.help": "Dimensioni e formato consigliati: 512x512, solo formato PNG. Se non è specificata alcuna icona touch, NodeBB tornerà a utilizzare la favicon.", "maskable-icon": "Icona Mascherabile (Schermata Iniziale)", "maskable-icon.help": "Dimensioni e formato consigliati: 512x512, solo formato PNG. Se non è specificata alcuna icona mascherabile, NodeBB tornerà a utilizzare l'Icona Touch.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Link in uscita", "outgoing-links.warning-page": "Usa pagina di avviso per i link in uscita", "search": "Cerca", diff --git a/public/language/it/admin/settings/notifications.json b/public/language/it/admin/settings/notifications.json index b8585b913b..60ec941a71 100644 --- a/public/language/it/admin/settings/notifications.json +++ b/public/language/it/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "Link a Notifica di benvenuto", "welcome-notification-uid": "Notifica di benvenuto utente (UID)", "post-queue-notification-uid": "Coda post utente (UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "Ritardo per l'invio delle email di notifica (secondi)", + "notification-delay-help": "Se l'utente ha letto la notifica entro questo periodo, l'email non sarà inviata.
Predefinito: 60 secondi." } \ No newline at end of file diff --git a/public/language/it/admin/settings/post.json b/public/language/it/admin/settings/post.json index 91330937cb..5941d29105 100644 --- a/public/language/it/admin/settings/post.json +++ b/public/language/it/admin/settings/post.json @@ -28,7 +28,7 @@ "restrictions.days-until-stale": "Giorni prima che l'argomento sia considerato vecchio", "restrictions.stale-help": "Se una discussione è considerata \"obsoleta\", verrà mostrato un avviso agli utenti che tentano di rispondere a quella discussione. (impostare a 0 per disabilitare)", "timestamp": "Data e Ora", - "timestamp.cut-off": "Data di interruzione (in giorni)", + "timestamp.cut-off": "Data limite (in giorni)", "timestamp.cut-off-help": "I tempi delle date verranno visualizzati in modo relativo (ad es. \"3 ore fa\" / \"5 giorni fa\") e localizzati in varie\n\t\t\t\t\tlingue. Dopo un certo punto, questo testo può essere cambiato per visualizzare la data localizzata\n\t\t\t\t\t(es. 5 Nov 2016 15:30).
(Predefinito: 30, o un mese).Impostare su 0 per visualizzare sempre le date, lasciare vuoto per visualizzare sempre i tempi relativi.", "timestamp.necro-threshold": "Necro Threshold (in giorni)", "timestamp.necro-threshold-help": "Un messaggio verrà mostrato tra i post se il tempo tra loro è più lungo della soglia necro. (Predefinito: 7, o una settimana). Impostare su 0 per disabilitare.
", @@ -40,7 +40,7 @@ "teaser.first": "Primo", "showPostPreviewsOnHover": "Mostra un'anteprima dei post quando il mouse ci passa sopra", "unread-and-recent": "Impostazioni Non letti e Recenti", - "unread.cutoff": "Giorni di interruzione non letti", + "unread.cutoff": "Giorni limite non letti", "unread.min-track-last": "Post minimi nella discussione prima di tracciare l'ultima lettura", "recent.max-topics": "Numero massimo di discussioni in atto/recenti", "recent.categoryFilter.disable": "Disabilita il filtro delle discussioni nelle categorie ignorate nella /pagina recente", diff --git a/public/language/it/admin/settings/reputation.json b/public/language/it/admin/settings/reputation.json index a718cc3f88..6e96ef6541 100644 --- a/public/language/it/admin/settings/reputation.json +++ b/public/language/it/admin/settings/reputation.json @@ -35,7 +35,7 @@ "flags.limit-user-flags-per-day-help": "Imposta a 0 per disabilitare, (predefinito: 10)", "flags.auto-flag-on-downvote-threshold": "Numero di voti negativi per segnalare automaticamente i post", "flags.auto-flag-on-downvote-threshold-help": "Imposta a 0 per disabilitare, (predefinito: 0)", - "flags.auto-resolve-on-ban": "Risolvi automaticamente tutti i ticket di un utente quando vengono bannati", + "flags.auto-resolve-on-ban": "Risolvi automaticamente tutti i ticket di un utente quando viene bannato", "flags.action-on-resolve": "Esegui le seguenti operazioni quando una segnalazione viene risolta", "flags.action-on-reject": "Esegui le seguenti operazioni quando una segnalazione viene rifiutata", "flags.action.nothing": "Non fare nulla", diff --git a/public/language/it/admin/settings/uploads.json b/public/language/it/admin/settings/uploads.json index e07c38c611..c01a5f8bf9 100644 --- a/public/language/it/admin/settings/uploads.json +++ b/public/language/it/admin/settings/uploads.json @@ -40,7 +40,7 @@ "default-avatar": "Personalizzazione Predefinita Avatar", "upload": "Carica", "profile-image-dimension": "Dimensione Immagine del profilo", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(in pixel, predefinito: 200 pixel)", "max-profile-image-size": "Dimensione Massima Immagine del Profile", "max-profile-image-size-help": "(in kibibytes, predefinito: 256 KiB)", "max-cover-image-size": "Dimensione massima dell'immagine di copertina", diff --git a/public/language/it/admin/settings/web-crawler.json b/public/language/it/admin/settings/web-crawler.json index 853b6f59f2..d65856962c 100644 --- a/public/language/it/admin/settings/web-crawler.json +++ b/public/language/it/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "Disabilita Feed RSS", "disable-sitemap-xml": "Disabilita Sitemap.xml", "sitemap-topics": "Numero di Discussioni da visualizzare in Mappa Sito", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "Durata della cache della mappa del sito (ore)", "clear-sitemap-cache": "Cancella Cache Mappa Sito", "view-sitemap": "Visualizza Mappa Sito" } \ No newline at end of file diff --git a/public/language/it/aria.json b/public/language/it/aria.json index 9b5eda125f..862dd3538f 100644 --- a/public/language/it/aria.json +++ b/public/language/it/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "Tag seguiti dall'utente", "delete-upload-button": "Pulsante annulla caricamento", "group-page-link-for": "Link alla pagina del gruppo per %1", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "Mostra post multipli" } \ No newline at end of file diff --git a/public/language/it/category.json b/public/language/it/category.json index 55682128c4..7ff47b1aeb 100644 --- a/public/language/it/category.json +++ b/public/language/it/category.json @@ -1,8 +1,8 @@ { "category": "Categoria", "subcategories": "Sottocategorie", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "Mondo", + "uncategorized.description": "Discussioni esterne a questo forum. Le opinioni e i punti di vista qui espressi potrebbero non riflettere quelli di questo forum e dei suoi membri.", "handle.description": "Questa categoria può essere seguita dal social web aperto tramite lo pseudonimo %1", "new-topic-button": "Nuova Discussione", "guest-login-post": "Accedi per postare", diff --git a/public/language/it/email.json b/public/language/it/email.json index a5f951783e..ec421f035f 100644 --- a/public/language/it/email.json +++ b/public/language/it/email.json @@ -55,7 +55,7 @@ "unsub.failure.message": "Sfortunatamente, non siamo stati in grado di cancellarti dalla mailing list, perché c'era un problema con il link. Tuttavia, puoi modificare le preferenze dell'email andando nelle impostazioni utente.

(errore: %1)", "banned.subject": "Sei stato bannato da %1", "banned.text1": "L'utente %1 è stato bannato da %2", - "banned.text2": "Questo ban durerà fino a %1.", + "banned.text2": "Questo ban durerà fino al %1.", "banned.text3": "Questo è il motivo per cui sei stato bannato:", "closing": "Grazie!" } \ No newline at end of file diff --git a/public/language/it/error.json b/public/language/it/error.json index ce37c002c0..9b8d425f37 100644 --- a/public/language/it/error.json +++ b/public/language/it/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Dati non validi", + "invalid-config-field-value": "Valore non valido per il campo di configurazione \"%1\": %2", "invalid-json": "JSON non valido", "wrong-parameter-type": "Era previsto un valore di tipo %3 per la proprietà '%1', ma invece è stato ricevuto %2", "required-parameters-missing": "I parametri richiesti sono mancanti in questa chiamata API: %1", @@ -32,7 +33,7 @@ "invalid-path": "Percorso non valido", "folder-exists": "La cartella esiste", "invalid-pagination-value": "Valore di impaginazione non valido, deve essere almeno %1 ed al massimo %2", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "Valore limite non letto non valido, deve essere almeno 1 e al massimo %1", "username-taken": "Nome utente già esistente", "email-taken": "L'indirizzo email è già stato utilizzato.", "email-nochange": "L'email inserita è la stessa dell'email già presente in archivio.", diff --git a/public/language/it/global.json b/public/language/it/global.json index 103c6f439d..4e6c15020d 100644 --- a/public/language/it/global.json +++ b/public/language/it/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "Le estensioni permesse dei file sono %1", "unsaved-changes": "Hai delle modifiche non salvate. Sei sicuro che vuoi lasciare la pagina?", "reconnecting-message": "Sembra che la tua connessione a %1 sia stata persa, per favore attendi mentre proviamo a riconnetterti.", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "Riconnessione a %1 riuscita.", "play": "Play", "cookies.message": "Questo sito utilizza i cookie per garantirti la miglior esperienza di navigazione possibile", "cookies.accept": "Ho capito!", diff --git a/public/language/it/groups.json b/public/language/it/groups.json index aa7e3ed339..84a1c2f22e 100644 --- a/public/language/it/groups.json +++ b/public/language/it/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "Gruppo", "all-groups": "Tutti i gruppi", "groups": "Gruppi", "members": "Membri", - "x-members": "%1 member(s)", + "x-members": "%1 membro(i)", "view-group": "Vedi Gruppo", "owner": "Proprietario del Gruppo", "new-group": "Crea Nuovo Gruppo", diff --git a/public/language/it/modules.json b/public/language/it/modules.json index 11b35b6989..b3703e230a 100644 --- a/public/language/it/modules.json +++ b/public/language/it/modules.json @@ -13,7 +13,7 @@ "chat.user-typing-1": "%1 sta scrivendo ...", "chat.user-typing-2": "%1 e %2 stanno scrivendo...", "chat.user-typing-3": "%1, %2 e %3 stanno scrivendo...", - "chat.user-typing-n": "%1, %2 e %3 stanno scrivendo...", + "chat.user-typing-n": "%1, %2 e %3 altri stanno scrivendo...", "chat.user-has-messaged-you": "%1 ti ha scritto.", "chat.replying-to": "Risposta a %1", "chat.see-all": "Tutte le chat", @@ -82,7 +82,7 @@ "composer.hide-preview": "Nascondi Anteprima", "composer.help": "Aiuto", "composer.user-said-in": "%1 ha detto in %2:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [detto](%2):", "composer.discard": "Sei sicuro di voler scartare questo post?", "composer.submit-and-lock": "Invia e Blocca", "composer.toggle-dropdown": "Mostra/Nascondi menu a discesa", diff --git a/public/language/it/notifications.json b/public/language/it/notifications.json index 143efee364..f072045fb8 100644 --- a/public/language/it/notifications.json +++ b/public/language/it/notifications.json @@ -65,7 +65,7 @@ "new-register-multiple": "Ci sono %1 richieste di registrazione che attendono di essere esaminate.", "flag-assigned-to-you": "Segnalazione %1 ti è stata assegnata", "post-awaiting-review": "Post in attesa di revisione", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "Discussione in attesa di revisione", "profile-exported": "%1 profilo esportato, clicca per scaricare", "posts-exported": "%1 post esportati, clicca per scaricare", "uploads-exported": "%1 caricamenti esportati, clicca per scaricare", diff --git a/public/language/it/pages.json b/public/language/it/pages.json index 351226874b..880041b252 100644 --- a/public/language/it/pages.json +++ b/public/language/it/pages.json @@ -19,7 +19,7 @@ "users/latest": "Ultimi Utenti", "users/sort-posts": "Utenti con il maggior numero di post", "users/sort-reputation": "Utenti con la reputazione più alta", - "users/banned": "Utenti Bannati", + "users/banned": "Utenti bannati", "users/most-flags": "Gli utenti più segnalati", "users/search": "Ricerca Utente", "notifications": "Notifiche", diff --git a/public/language/it/search.json b/public/language/it/search.json index 7888ce550d..6fc0b60f05 100644 --- a/public/language/it/search.json +++ b/public/language/it/search.json @@ -14,7 +14,7 @@ "categories": "Categorie", "all-categories": "Tutte le categorie", "categories-x": "Categorie: %1", - "categories-watched-categories": "Categorie: Categorie osservate", + "categories-watched-categories": "Categorie: Categorie seguite", "type-a-category": "Digita una categoria", "tags": "Tag", "tags-x": "Tag: %1", diff --git a/public/language/it/themes/harmony.json b/public/language/it/themes/harmony.json index 1875f5fdb6..07a7320d3b 100644 --- a/public/language/it/themes/harmony.json +++ b/public/language/it/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Tema Armonia", "skins": "Skin", - "light": "Light", - "dark": "Dark", + "light": "Chiaro", + "dark": "Scuro", "collapse": "Collassa", "expand": "Espandi", "sidebar-toggle": "Attiva/disattiva barra laterale", diff --git a/public/language/it/topic.json b/public/language/it/topic.json index e77ffd1bfe..9a0472f63d 100644 --- a/public/language/it/topic.json +++ b/public/language/it/topic.json @@ -225,7 +225,7 @@ "no-more-next-post": "Non hai più post in questa discussione", "open-composer": "Apri compositore", "post-quick-reply": "Risposta rapida", - "post-quick-create": "Quick post", + "post-quick-create": "Post rapido", "navigator.index": "Post %1 di %2", "navigator.unread": "%1 non letto", "upvote-post": "Vota positivamente il post", diff --git a/public/language/it/world.json b/public/language/it/world.json index 335b065b51..3af26b4563 100644 --- a/public/language/it/world.json +++ b/public/language/it/world.json @@ -1,12 +1,14 @@ { "name": "Mondo", "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", - "recent": "All", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", + "popular-day": "Popolare (Giorno)", + "popular-week": "Popolare (Settimana)", + "popular-month": "Popolare (Mese)", + "popular-year": "Popolare (Anno)", + "popular-alltime": "Popolare (Tutto il tempo)", + "recent": "Tutto", "help": "Aiuto", "help.title": "Cos'è questa pagina?", @@ -16,10 +18,12 @@ "help.federating": "Allo stesso modo, se gli utenti esterni a questo forum iniziano a seguirti, i tuoi post inizieranno ad apparire anche su quelle app e quei siti web.", "help.next-generation": "Questa è la prossima generazione di social media, inizia a contribuire oggi!", - "onboard.title": "La tua finestra sul fediverso...", - "onboard.what": "Questa è la tua categoria personalizzata composta solo da contenuti trovati al di fuori di questo forum. La presenza di qualcosa in questa pagina dipende dal fatto che tu la segua o che il post sia stato condiviso da qualcuno che segui.", - "onboard.why": "Ci sono molte cose che accadono al di fuori di questo forum e non tutte sono rilevanti per i tuoi interessi. Ecco perché seguire le persone è il modo migliore per segnalare che vuoi vedere di più da qualcuno.", - "onboard.how": "Nel frattempo, puoi cliccare sui pulsanti di scelta rapida in alto per vedere cos'altro conosce questo forum e iniziare a scoprire nuovi contenuti!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Trova una categoria...", + "see-more": "Vedi di più", + "see-less": "Vedi meno" } \ No newline at end of file diff --git a/public/language/ja/admin/advanced/cache.json b/public/language/ja/admin/advanced/cache.json index a340f89ba1..05094e56a7 100644 --- a/public/language/ja/admin/advanced/cache.json +++ b/public/language/ja/admin/advanced/cache.json @@ -1,5 +1,5 @@ { - "cache": "Cache", + "cache": "キャッシュ", "percent-full": "%1% がフル", "post-cache-size": "投稿キャッシュのサイズ", "items-in-cache": "キャッシュ内のアイテム" diff --git a/public/language/ja/admin/advanced/database.json b/public/language/ja/admin/advanced/database.json index eb88f04b1f..f1377df5f7 100644 --- a/public/language/ja/admin/advanced/database.json +++ b/public/language/ja/admin/advanced/database.json @@ -17,7 +17,7 @@ "mongo.file-size": "ファイルサイズ", "mongo.resident-memory": "常駐メモリ", "mongo.virtual-memory": "仮想メモリ", - "mongo.mapped-memory": "Mapped Memory", + "mongo.mapped-memory": "マップトメモリ", "mongo.bytes-in": "バイト数", "mongo.bytes-out": "バイトアウト", "mongo.num-requests": "リクエスト数", diff --git a/public/language/ja/admin/advanced/events.json b/public/language/ja/admin/advanced/events.json index cde8111fca..9f82505311 100644 --- a/public/language/ja/admin/advanced/events.json +++ b/public/language/ja/admin/advanced/events.json @@ -2,16 +2,16 @@ "events": "イベント", "no-events": "イベントがありません", "control-panel": "イベントのコントロールパネル", - "delete-events": "Delete Events", - "confirm-delete-all-events": "Are you sure you want to delete all logged events?", - "filters": "Filters", - "filters-apply": "Apply Filters", - "filter-type": "Event Type", - "filter-start": "Start Date", - "filter-end": "End Date", - "filter-user": "Filter by User", - "filter-user.placeholder": "Type user name to filter...", - "filter-group": "Filter by Group", - "filter-group.placeholder": "Type group name to filter...", - "filter-per-page": "Per Page" + "delete-events": "イベントを削除", + "confirm-delete-all-events": "記録されたすべてのイベントを削除してもよろしいですか?", + "filters": "フィルター", + "filters-apply": "フィルターを適用", + "filter-type": "イベントタイプ", + "filter-start": "開始日", + "filter-end": "終了日", + "filter-user": "ユーザーでフィルター", + "filter-user.placeholder": "フィルターするユーザー名を入力...", + "filter-group": "グループでフィルター", + "filter-group.placeholder": "フィルターするグループ名を入力...", + "filter-per-page": "1ページあたり" } \ No newline at end of file diff --git a/public/language/ja/admin/advanced/jobs.json b/public/language/ja/admin/advanced/jobs.json new file mode 100644 index 0000000000..2cf132d0d6 --- /dev/null +++ b/public/language/ja/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "ジョブ", + "job-name": "ジョブ名", + "schedule": "スケジュール", + "next-run": "次を実行", + "last-duration": "前回の所要時間", + "running": "実行中", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ja/admin/dashboard.json b/public/language/ja/admin/dashboard.json index 569433e14d..9b28fc4394 100644 --- a/public/language/ja/admin/dashboard.json +++ b/public/language/ja/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "スレッド", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "過去7日間", "page-views-thirty": "過去30日間", "page-views-last-day": "過去24時間", - "page-views-custom": "カスタム期間", + "page-views-custom": "Custom Range", "page-views-custom-start": "期間開始", "page-views-custom-end": "期間終了", "page-views-custom-help": "表示したいページビューの日付範囲を入力します。日付選択ツールが使用できない場合、受け入れ可能な形式は次のとおりです。YYYY-MM-DD", diff --git a/public/language/ja/admin/manage/users.json b/public/language/ja/admin/manage/users.json index baa35893ed..3f2408fd56 100644 --- a/public/language/ja/admin/manage/users.json +++ b/public/language/ja/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "1ページあたり250 件", "500-per-page": "1ページあたり500 件", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "ユーザーID別", "search.uid-placeholder": "検索するユーザーIDを入力してください", "search.username": "ユーザー名別", diff --git a/public/language/ja/admin/menu.json b/public/language/ja/admin/menu.json index 685c73aec5..346c3f38d0 100644 --- a/public/language/ja/admin/menu.json +++ b/public/language/ja/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "ログ", "advanced/errors": "エラー", "advanced/cache": "キャッシュ", + "advanced/jobs": "Jobs", "development/logger": "ロガー", "development/info": "情報", diff --git a/public/language/ja/admin/settings/activitypub.json b/public/language/ja/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/ja/admin/settings/activitypub.json +++ b/public/language/ja/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ja/admin/settings/chat.json b/public/language/ja/admin/settings/chat.json index bd74261bd1..26617ee3d1 100644 --- a/public/language/ja/admin/settings/chat.json +++ b/public/language/ja/admin/settings/chat.json @@ -5,11 +5,11 @@ "disable-editing": "チャットメッセージの編集/削除を無効にする", "disable-editing-help": "管理者およびグローバルモデレーターはこの制限を免除されます", "max-length": "チャットメッセージの最大の長さ", - "max-length-remote": "Maximum length of remote chat messages", - "max-length-remote-help": "This value is usually set higher than the chat message maximum for local users as remote messages tend to be longer (with @ mentions, etc.)", - "max-chat-room-name-length": "Maximum length of chat room names", + "max-length-remote": "リモートチャットメッセージの最大長", + "max-length-remote-help": "リモートメッセージは通常長いため(@メンションなど)、この値はローカルユーザー用のチャットメッセージ最大値より高く設定されることが多いです。", + "max-chat-room-name-length": "チャットルーム名の最大長", "max-room-size": "チャットルームの最大ユーザー数", - "delay": "Time between chat messages (ms)", - "restrictions.seconds-edit-after": "Number of seconds a chat message will remain editable.", - "restrictions.seconds-delete-after": "Number of seconds a chat message will remain deletable." + "delay": "チャットメッセージ間の時間(ミリ秒)", + "restrictions.seconds-edit-after": "投稿が編集可能な秒数", + "restrictions.seconds-delete-after": "投稿が削除可能な秒数" } \ No newline at end of file diff --git a/public/language/ja/admin/settings/general.json b/public/language/ja/admin/settings/general.json index 2d79a2bc35..f3f623f970 100644 --- a/public/language/ja/admin/settings/general.json +++ b/public/language/ja/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "サイトのキーワード", "keywords-placeholder": "あなたのコミュニティを記述するキーワード、カンマ区切り", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "画像", "logo.image-placeholder": "フォーラムのヘッダーに表示するロゴのパス", "logo.upload": "アップロード", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "外部サイトへのリンク", "outgoing-links.warning-page": "送信リンクの警告ページを使用", "search": "Search", diff --git a/public/language/ja/aria.json b/public/language/ja/aria.json index ec7889d2f4..a2b938dd30 100644 --- a/public/language/ja/aria.json +++ b/public/language/ja/aria.json @@ -1,10 +1,10 @@ { - "post-sort-option": "Post sort option, %1", - "topic-sort-option": "Topic sort option, %1", - "user-avatar-for": "User avatar for %1", - "profile-page-for": "Profile page for user %1", - "user-watched-tags": "User watched tags", - "delete-upload-button": "Delete upload button", - "group-page-link-for": "Group page link for %1", - "show-crossposts": "Show Cross-posts" + "post-sort-option": "投稿の並び替えオプション、%1", + "topic-sort-option": "スレッドの並び替えオプション、%1", + "user-avatar-for": "%1のユーザーアバター", + "profile-page-for": "ユーザー%1のプロフィールページ", + "user-watched-tags": "ユーザーのウォッチ中のタグ", + "delete-upload-button": "アップロード削除ボタン", + "group-page-link-for": "グループ%1のページリンク", + "show-crossposts": "クロスポストを表示" } \ No newline at end of file diff --git a/public/language/ja/category.json b/public/language/ja/category.json index 80ac25539f..573a5d6260 100644 --- a/public/language/ja/category.json +++ b/public/language/ja/category.json @@ -1,30 +1,30 @@ { "category": "カテゴリ", "subcategories": "サブカテゴリ", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", - "handle.description": "This category can be followed from the open social web via the handle %1", + "uncategorized": "世界", + "uncategorized.description": "このフォーラム外からのトピック。ここに表示される見解や意見は、このフォーラムおよびそのメンバーの見解を反映しない場合があります。", + "handle.description": "このカテゴリはオープンソーシャルウェブからハンドル %1 でフォローできます", "new-topic-button": "新規スレッド", "guest-login-post": "投稿するにはログインしてください", "no-topics": "まだスレッドはありません
最初のスレッドを書いてみませんか?", - "no-followers": "Nobody on this website is tracking or watching this category. Track or watch this category in order to begin receiving updates.", + "no-followers": "このウェブサイトでこのカテゴリを追跡またはウォッチしている人はいません。更新を受け取るにはカテゴリを追跡またはウォッチしてください。", "browsing": "閲覧中", "no-replies": "返事はまだありません", "no-new-posts": "新しい投稿はありません", "watch": "ウォッチする", "ignore": "無視する", "watching": "ウォッチ中", - "tracking": "Tracking", - "not-watching": "Not Watching", + "tracking": "追跡中", + "not-watching": "ウォッチしていない", "ignoring": "無視中", - "watching.description": "Notify me of new topics.
Show topics in unread & recent", - "tracking.description": "Shows topics in unread & recent", - "not-watching.description": "Do not show topics in unread, show in recent", - "ignoring.description": "Do not show topics in unread & recent", - "watching.message": "You are now watching updates from this category and all subcategories", - "tracking.message": "You are now tracking updates from this category and all subcategories", - "notwatching.message": "You are not watching updates from this category and all subcategories", - "ignoring.message": "You are now ignoring updates from this category and all subcategories", + "watching.description": "新しいスレッドの通知を受け取る。
未読と最近にスレッドを表示", + "tracking.description": "未読と最近にスレッドを表示", + "not-watching.description": "未読には表示しない、最近に表示", + "ignoring.description": "未読にも最近にも表示しない", + "watching.message": "このカテゴリとすべてのサブカテゴリの更新をウォッチしています", + "tracking.message": "このカテゴリとすべてのサブカテゴリの更新を追跡しています", + "notwatching.message": "このカテゴリとサブカテゴリの更新をウォッチしていません", + "ignoring.message": "このカテゴリとサブカテゴリの更新を無視しています", "watched-categories": "ウォッチ中のカテゴリ", - "x-more-categories": "%1 more categories" + "x-more-categories": "あと%1件のカテゴリ" } \ No newline at end of file diff --git a/public/language/ja/email.json b/public/language/ja/email.json index 777dee46bd..c2798646ea 100644 --- a/public/language/ja/email.json +++ b/public/language/ja/email.json @@ -1,58 +1,58 @@ { - "test-email.subject": "Test Email", - "password-reset-requested": "Password Reset Requested!", + "test-email.subject": "テストメール", + "password-reset-requested": "パスワードリセットのリクエスト", "welcome-to": "%1へようこそ!", "invite": "%1からの招待です", "greeting-no-name": "こんにちは", "greeting-with-name": "%1さん、こんにちは", - "email.verify-your-email.subject": "Please verify your email", - "email.verify.text1": "You've requested that we change or confirm your email address", - "email.verify.text2": "For security purposes, we only change or confirm the email address on file once its ownership has been confirmed via email. If you did not request this, no action is required on your part.", - "email.verify.text3": "Once you confirm this email address, we will replace your current email address with this one (%1).", + "email.verify-your-email.subject": "メールアドレスの確認をお願いします", + "email.verify.text1": "メールアドレスの変更または確認をリクエストされました", + "email.verify.text2": "セキュリティのため、メールで所有権が確認された場合のみ、登録されているメールアドレスを変更または確認します。このリクエストをしていない場合は、何もする必要はありません。", + "email.verify.text3": "このメールアドレスを確認すると、現在のメールアドレスをこのアドレス(%1)に置き換えます。", "welcome.text1": "%1に登録していただき、ありがとうございます!", "welcome.text2": "あなたのアカウントを完全に有効化するには、アドレスが正しいことを確認する必要があります。", "welcome.text3": "管理者があなたの登録申請を承認しました。これから、自分のユーザ名とパスワードでログインできます。", "welcome.cta": "ここをクリックしてメールアドレスの確認を行ってください", "invitation.text1": "%1さんがあなたを%2に招待しました", - "invitation.text2": "Your invitation will expire in %1 days.", - "invitation.cta": "Click here to create your account.", + "invitation.text2": "招待の有効期限は%1日です。", + "invitation.cta": "ここをクリックしてアカウントを作成", "reset.text1": "パスワードリセットのリクエストを受け付けました。リクエストしていない場合はこのメールは無視してください。", "reset.text2": "パスワードをリセットするには、次のリンクにクリックしてください:", "reset.cta": "パスワードをリセットするには、ここをクリックしてください", "reset.notify.subject": "パスワードをリセットしました", "reset.notify.text1": "%1にてパスワードのリセットが行われたことをお知らせします。", "reset.notify.text2": "もしあなたがリセットを行っていない場合は、すぐに管理者に通報してください。", - "digest.unread-rooms": "Unread rooms", - "digest.room-name-unreadcount": "%1 (%2 unread)", + "digest.unread-rooms": "未読のルーム", + "digest.room-name-unreadcount": "%1(%2件未読)", "digest.latest-topics": "%1からの新しいスレッド", - "digest.top-topics": "Top topics from %1", - "digest.popular-topics": "Popular topics from %1", + "digest.top-topics": "%1の人気スレッド", + "digest.popular-topics": "%1の人気スレッド", "digest.cta": "クリックで%1を見る", "digest.unsub.info": "このまとめはあなたの購読設定により送られました。", "digest.day": "日", "digest.week": "週", "digest.month": "月", "digest.subject": "%1のダイジェスト", - "digest.title.day": "Your Daily Digest", - "digest.title.week": "Your Weekly Digest", - "digest.title.month": "Your Monthly Digest", - "notif.chat.new-message-from-user": "New message from \"%1\"", - "notif.chat.new-message-from-user-in-room": "New message from %1 in room %2", + "digest.title.day": "デイリーダイジェスト", + "digest.title.week": "ウィークリーダイジェスト", + "digest.title.month": "マンスリーダイジェスト", + "notif.chat.new-message-from-user": "「%1」からの新しいメッセージ", + "notif.chat.new-message-from-user-in-room": "ルーム%2で%1からの新しいメッセージ", "notif.chat.cta": "クリックして会話を続ける", "notif.chat.unsub.info": "このチャットの通知はあなたの購読設定により送られました。", "notif.post.unsub.info": "この投稿の通知はあなたの購読設定により送られました。", - "notif.post.unsub.one-click": "Alternatively, unsubscribe from future emails like this, by clicking", - "notif.cta": "To the forum", - "notif.cta-new-reply": "View Post", - "notif.cta-new-chat": "View Chat", - "notif.test.short": "Testing Notifications", - "notif.test.long": "This is a test of the notifications email. Send help!", + "notif.post.unsub.one-click": "または、以下のリンクをクリックしてこのようなメールの配信を停止できます", + "notif.cta": "フォーラムへ", + "notif.cta-new-reply": "投稿を表示", + "notif.cta-new-chat": "チャットを表示", + "notif.test.short": "通知のテスト", + "notif.test.long": "これは通知メールのテストです。", "test.text1": "このメールはNodeBBのメーラー(emailer)が正しく設定されているか確認をするためのメールです。", "unsub.cta": "ここをクリックして設定を変更する", - "unsubscribe": "unsubscribe", - "unsub.success": "You will no longer receive emails from the %1 mailing list", - "unsub.failure.title": "Unable to unsubscribe", - "unsub.failure.message": "Unfortunately, we were not able to unsubscribe you from the mailing list, as there was an issue with the link. However, you can alter your email preferences by going to your user settings.

(error: %1)", + "unsubscribe": "購読解除", + "unsub.success": "%1のメーリングリストからのメールは届かなくなります", + "unsub.failure.title": "配信停止できませんでした", + "unsub.failure.message": "リンクに問題があったため、メーリングリストの配信を停止できませんでした。ただし、ユーザー設定でメール設定を変更できます。

(エラー: %1)", "banned.subject": "%1さんからBANされました。", "banned.text1": "%1さんは%2さんにBANされています。", "banned.text2": "このBANは%1まで続きます。", diff --git a/public/language/ja/error.json b/public/language/ja/error.json index a2a23aa91f..27b7f6c063 100644 --- a/public/language/ja/error.json +++ b/public/language/ja/error.json @@ -1,5 +1,6 @@ { "invalid-data": "無効なデータ", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "無効なJSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/ja/ip-blacklist.json b/public/language/ja/ip-blacklist.json index 2bcc4d5b9a..3303b69bcc 100644 --- a/public/language/ja/ip-blacklist.json +++ b/public/language/ja/ip-blacklist.json @@ -1,19 +1,19 @@ { - "lead": "IPブラックリストをこちらで設定します。", - "description": "場合によては、ユーザーアカウントを禁止せざるを得ないこともあります。フォーラムを保護するための最善の方法は、特定のIPまたはIPの範囲へのアクセスを制限することです。このような場合は、厄介なIPアドレスまたはCIDRブロック全体をこのブラックリストに追加することができ、新しいアカウントにログインしたり登録することができなくなります。", + "lead": "ここでIPブラックリストを設定します。", + "description": "ユーザーアカウントのBANでは不十分な場合があります。また、特定のIPまたはIP範囲へのアクセスを制限することがフォーラムを保護する最善の方法である場合もあります。このような状況では、問題のあるIPアドレスまたはCIDRブロック全体をこのブラックリストに追加でき、ログインや新規アカウント登録ができなくなります。", "active-rules": "アクティブルール", "validate": "ブラックリストの検証", - "apply": "ブラックリスト", + "apply": "ブラックリストを適用", "hints": "構文のヒント", - "hint-1": "1行に1つのIPアドレスを定義します。あなたはCIDR形式(例: 192.168.100.0/22 )に従っている限り、IPブロックを追加できます。", - "hint-2": "記号でコメントを追加することができます。", + "hint-1": "1行に1つのIPアドレスを定義します。CIDR形式(例:192.168.100.0/22)に従っている限り、IPブロックを追加できます。", + "hint-2": "#記号で始まる行でコメントを追加できます。", - "validate.x-valid": "%2のルールのうち%1 のルール(s) が有効です。", - "validate.x-invalid": "次の%1 ルールは無効:", + "validate.x-valid": " %2件のルールのうち%1件が有効です。", + "validate.x-invalid": "次の%1件のルールは無効です:", - "alerts.applied-success": "ブラックリストに適用されました", + "alerts.applied-success": "ブラックリストを適用しました", - "analytics.blacklist-hourly": "Figure 1 – Blacklist hits per hour", - "analytics.blacklist-daily": "Figure 2 – Blacklist hits per day", - "ip-banned": "IP banned" + "analytics.blacklist-hourly": "図1 – 1時間あたりのブラックリストヒット", + "analytics.blacklist-daily": "図2 – 1日あたりのブラックリストヒット", + "ip-banned": "IP禁止" } \ No newline at end of file diff --git a/public/language/ja/world.json b/public/language/ja/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/ja/world.json +++ b/public/language/ja/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/ko/admin/advanced/jobs.json b/public/language/ko/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ko/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ko/admin/dashboard.json b/public/language/ko/admin/dashboard.json index 16e875a7c4..fa3c1753cf 100644 --- a/public/language/ko/admin/dashboard.json +++ b/public/language/ko/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "토픽", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "지난 7일", "page-views-thirty": "지난 30일", "page-views-last-day": "지난 24시간", - "page-views-custom": "사용자 정의 날짜 범위", + "page-views-custom": "Custom Range", "page-views-custom-start": "시작 범위", "page-views-custom-end": "종료 범위", "page-views-custom-help": "보고 싶은 페이지 뷰의 날짜 범위를 입력하세요. 날짜 선택기를 사용할 수 없는 경우 허용되는 형식은 YYYY-MM-DD입니다.", diff --git a/public/language/ko/admin/manage/users.json b/public/language/ko/admin/manage/users.json index 09c51afc70..3f85b2cbeb 100644 --- a/public/language/ko/admin/manage/users.json +++ b/public/language/ko/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "페이지당 250개", "500-per-page": "페이지당 500개", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "사용자 ID로 검색", "search.uid-placeholder": "검색할 사용자 ID를 입력", "search.username": "사용자 이름으로 검색", diff --git a/public/language/ko/admin/menu.json b/public/language/ko/admin/menu.json index 684fcdcbae..7a43bf258a 100644 --- a/public/language/ko/admin/menu.json +++ b/public/language/ko/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "로그", "advanced/errors": "오류", "advanced/cache": "캐시", + "advanced/jobs": "Jobs", "development/logger": "로거", "development/info": "정보", diff --git a/public/language/ko/admin/settings/activitypub.json b/public/language/ko/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/ko/admin/settings/activitypub.json +++ b/public/language/ko/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ko/admin/settings/general.json b/public/language/ko/admin/settings/general.json index 0756494d50..a2f98a64bf 100644 --- a/public/language/ko/admin/settings/general.json +++ b/public/language/ko/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "사이트 키워드", "keywords-placeholder": "커뮤니티를 설명하는 키워드, 쉼표로 구분", - "logo-and-icons": "사이트 로고 & 아이콘", + "logo-and-icons": "Media & Branding", "logo.image": "이미지", "logo.image-placeholder": "포럼 헤더에 표시할 로고의 경로", "logo.upload": "업로드", @@ -35,6 +35,8 @@ "touch-icon.help": "권장 크기 및 형식: 512x512, PNG 형식만. 터치 아이콘을 지정하지 않은 경우 NodeBB는 파비콘을 사용합니다.", "maskable-icon": "Maskable (홈 화면) 아이콘", "maskable-icon.help": "권장 크기 및 형식: 512x512, PNG 형식만. 마스크 가능 아이콘을 지정하지 않은 경우 NodeBB는 터치 아이콘을 사용합니다.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "외부로 나가는 링크", "outgoing-links.warning-page": "외부 링크 경고 페이지 사용", "search": "검색", diff --git a/public/language/ko/error.json b/public/language/ko/error.json index a5e03c05bb..c2338ddba4 100644 --- a/public/language/ko/error.json +++ b/public/language/ko/error.json @@ -1,5 +1,6 @@ { "invalid-data": "잘못된 데이터", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "잘못된 JSON", "wrong-parameter-type": "속성 `%1`에 대해 %3 유형의 값이 예상되었지만 대신 %2가 수신되었습니다", "required-parameters-missing": "이 API 호출에서 필수 매개변수가 누락되었습니다: %1", diff --git a/public/language/ko/world.json b/public/language/ko/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/ko/world.json +++ b/public/language/ko/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/lt/admin/advanced/jobs.json b/public/language/lt/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/lt/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/lt/admin/dashboard.json b/public/language/lt/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/lt/admin/dashboard.json +++ b/public/language/lt/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/lt/admin/manage/users.json b/public/language/lt/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/lt/admin/manage/users.json +++ b/public/language/lt/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/lt/admin/menu.json b/public/language/lt/admin/menu.json index 5c6f513bcd..6e45aafa29 100644 --- a/public/language/lt/admin/menu.json +++ b/public/language/lt/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/lt/admin/settings/activitypub.json b/public/language/lt/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/lt/admin/settings/activitypub.json +++ b/public/language/lt/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/lt/admin/settings/general.json b/public/language/lt/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/lt/admin/settings/general.json +++ b/public/language/lt/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/lt/error.json b/public/language/lt/error.json index cc11db5dab..b70c8a2fe3 100644 --- a/public/language/lt/error.json +++ b/public/language/lt/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Klaidingi duomenys", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Nevalidus JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/lt/world.json b/public/language/lt/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/lt/world.json +++ b/public/language/lt/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/lv/admin/advanced/jobs.json b/public/language/lv/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/lv/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/lv/admin/dashboard.json b/public/language/lv/admin/dashboard.json index ab1a3e641f..383b7fa919 100644 --- a/public/language/lv/admin/dashboard.json +++ b/public/language/lv/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Temati", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Pēdējās 7 dienās", "page-views-thirty": "Pēdējās 30 dienās", "page-views-last-day": "Pēdējās 24 stundās", - "page-views-custom": "Pielāgotais datumu diapazons", + "page-views-custom": "Custom Range", "page-views-custom-start": "No", "page-views-custom-end": "Līdz", "page-views-custom-help": "Ievadīt datumu diapazonu, kā lapu skatījumu skaitu vēlies redzēt. Ja datumu atlasītājs nav pieejams, lietot formātu YYYY-MM-DD", diff --git a/public/language/lv/admin/manage/users.json b/public/language/lv/admin/manage/users.json index 1979a26cfb..c28c36dc3d 100644 --- a/public/language/lv/admin/manage/users.json +++ b/public/language/lv/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Pēc lietotāja ID", "search.uid-placeholder": "Meklējamais lietotāja ID", "search.username": "Pēc lietotājvārda", diff --git a/public/language/lv/admin/menu.json b/public/language/lv/admin/menu.json index e7dbbbd256..5f4a4fb057 100644 --- a/public/language/lv/admin/menu.json +++ b/public/language/lv/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Žurnāls", "advanced/errors": "Kļūdu žurnāls", "advanced/cache": "Kešatmiņa", + "advanced/jobs": "Jobs", "development/logger": "Atkļūdošanas žurnāls", "development/info": "Informācija", diff --git a/public/language/lv/admin/settings/activitypub.json b/public/language/lv/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/lv/admin/settings/activitypub.json +++ b/public/language/lv/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/lv/admin/settings/general.json b/public/language/lv/admin/settings/general.json index fabfbb824e..2d306b6508 100644 --- a/public/language/lv/admin/settings/general.json +++ b/public/language/lv/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Foruma atslēgvārdi", "keywords-placeholder": "Atslēgvārdi, kas apraksta forumu, atdalīti ar komatu", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Bilde", "logo.image-placeholder": "Ceļš uz logo, ko parādītu foruma galvenē", "logo.upload": "Augšupielādēt", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Izejošās saites", "outgoing-links.warning-page": "Lietot izejošo saišu brīdinājuma lapu", "search": "Search", diff --git a/public/language/lv/error.json b/public/language/lv/error.json index e7bee30889..d251b3c149 100644 --- a/public/language/lv/error.json +++ b/public/language/lv/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Nederīgi dati", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Nederīgs JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/lv/world.json b/public/language/lv/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/lv/world.json +++ b/public/language/lv/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/ms/admin/advanced/jobs.json b/public/language/ms/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ms/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ms/admin/dashboard.json b/public/language/ms/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/ms/admin/dashboard.json +++ b/public/language/ms/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/ms/admin/manage/users.json b/public/language/ms/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/ms/admin/manage/users.json +++ b/public/language/ms/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/ms/admin/menu.json b/public/language/ms/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/ms/admin/menu.json +++ b/public/language/ms/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/ms/admin/settings/activitypub.json b/public/language/ms/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/ms/admin/settings/activitypub.json +++ b/public/language/ms/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ms/admin/settings/general.json b/public/language/ms/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/ms/admin/settings/general.json +++ b/public/language/ms/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/ms/error.json b/public/language/ms/error.json index c15944594b..340a14711b 100644 --- a/public/language/ms/error.json +++ b/public/language/ms/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Data Tak Sah", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/ms/world.json b/public/language/ms/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/ms/world.json +++ b/public/language/ms/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/nb/admin/advanced/jobs.json b/public/language/nb/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/nb/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/nb/admin/dashboard.json b/public/language/nb/admin/dashboard.json index 125cf573b1..80779fe19f 100644 --- a/public/language/nb/admin/dashboard.json +++ b/public/language/nb/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Emner", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Siste 7 dager", "page-views-thirty": "Siste 30 dager", "page-views-last-day": "Siste 24 timer", - "page-views-custom": "Egendefinert datoperiode", + "page-views-custom": "Custom Range", "page-views-custom-start": "Startdato", "page-views-custom-end": "Sluttdato", "page-views-custom-help": "Angi et datointervall for sidevisninger du vil se. Hvis ingen datovelger er tilgjengelig, bruk formatet YYYY-MM-DD", diff --git a/public/language/nb/admin/manage/users.json b/public/language/nb/admin/manage/users.json index 1a260af90c..c02fecd70b 100644 --- a/public/language/nb/admin/manage/users.json +++ b/public/language/nb/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per side", "500-per-page": "500 per side", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Etter bruker-ID", "search.uid-placeholder": "Skriv inn en bruker-ID for å søke", "search.username": "Etter brukernavn", diff --git a/public/language/nb/admin/menu.json b/public/language/nb/admin/menu.json index 6cd98eb59e..0cea6aed2f 100644 --- a/public/language/nb/admin/menu.json +++ b/public/language/nb/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logger", "advanced/errors": "Feil", "advanced/cache": "Buffer", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/nb/admin/settings/activitypub.json b/public/language/nb/admin/settings/activitypub.json index 312603a4ff..63597bafc7 100644 --- a/public/language/nb/admin/settings/activitypub.json +++ b/public/language/nb/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/nb/admin/settings/general.json b/public/language/nb/admin/settings/general.json index 17d717b787..15d189e51f 100644 --- a/public/language/nb/admin/settings/general.json +++ b/public/language/nb/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Nøkkelord for nettstedet", "keywords-placeholder": "Nøkkelord som beskriver fellesskapet ditt, kommaseparert", - "logo-and-icons": "Logo og ikoner for nettstedet", + "logo-and-icons": "Media & Branding", "logo.image": "Bilde", "logo.image-placeholder": "Sti til et logo som vises i forumets topptekst", "logo.upload": "Last opp", @@ -35,6 +35,8 @@ "touch-icon.help": "Anbefalt størrelse og format: 512x512, kun PNG-format. Hvis ingen berøringsikon er spesifisert, brukes favicon som reserve.", "maskable-icon": "Maskerbart (Hjem-skjerm) ikon", "maskable-icon.help": "Anbefalt størrelse og format: 512x512, kun PNG-format. Hvis ingen maskerbart ikon er spesifisert, brukes berøringsikon som reserve.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Utgående lenker", "outgoing-links.warning-page": "Bruk varslingsside for utgående lenker", "search": "Søk", diff --git a/public/language/nb/error.json b/public/language/nb/error.json index 8d91f07834..ed5e55d722 100644 --- a/public/language/nb/error.json +++ b/public/language/nb/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ugyldige data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Ugyldig JSON", "wrong-parameter-type": "En verdi av typen %3 var forventet for egenskapen `%1`, men %2 ble mottatt i stedet", "required-parameters-missing": "Nødvendige parametere manglet fra dette API-kallet: %1", diff --git a/public/language/nb/world.json b/public/language/nb/world.json index 598234cf03..62c2f9ddde 100644 --- a/public/language/nb/world.json +++ b/public/language/nb/world.json @@ -1,6 +1,8 @@ { "name": "Verden", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "Dette er neste generasjon sosiale medier, begynn å bidra i dag!", - "onboard.title": "Ditt vindu til fødiverset...", - "onboard.what": "Dette er din personlige kategori, som kun består av innhold funnet utenfor dette forumet. Om noe vises på denne siden, avhenger av om du følger dem, eller om innlegget ble delt av noen du følger.", - "onboard.why": "Det skjer mye utenfor dette forumet, og ikke alt er relevant for dine interesser. Derfor er det å følge folk den beste måten å vise at du vil se mer fra noen.", - "onboard.how": "I mellomtiden kan du klikke på snarveisknappene øverst for å se hva annet dette forumet inneholder, og begynne å oppdage nytt innhold!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/nl/admin/advanced/jobs.json b/public/language/nl/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/nl/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/nl/admin/dashboard.json b/public/language/nl/admin/dashboard.json index 0331e7c2bb..141e50278a 100644 --- a/public/language/nl/admin/dashboard.json +++ b/public/language/nl/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Onderwerpen", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/nl/admin/manage/users.json b/public/language/nl/admin/manage/users.json index d67da5a976..68a22af4f8 100644 --- a/public/language/nl/admin/manage/users.json +++ b/public/language/nl/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/nl/admin/menu.json b/public/language/nl/admin/menu.json index 8316ab0c3f..a9d7ed3a5b 100644 --- a/public/language/nl/admin/menu.json +++ b/public/language/nl/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Fouten", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Informatie", diff --git a/public/language/nl/admin/settings/activitypub.json b/public/language/nl/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/nl/admin/settings/activitypub.json +++ b/public/language/nl/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/nl/admin/settings/general.json b/public/language/nl/admin/settings/general.json index a5828eaa84..4a450b7aff 100644 --- a/public/language/nl/admin/settings/general.json +++ b/public/language/nl/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Trefwoorden", "keywords-placeholder": "Trefwoorden die uw community beschrijven, kommagescheiden", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Afbeelding", "logo.image-placeholder": "Pad naar een logo om te tonen op de forum header", "logo.upload": "Uploaden", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Uitgaande links", "outgoing-links.warning-page": "Gebruik waarschuwingspagina voor uitgaande links", "search": "Search", diff --git a/public/language/nl/error.json b/public/language/nl/error.json index 4e30f62ae8..77f8914364 100644 --- a/public/language/nl/error.json +++ b/public/language/nl/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ongeldige data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Ongeldige JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/nl/world.json b/public/language/nl/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/nl/world.json +++ b/public/language/nl/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/nn-NO/admin/advanced/jobs.json b/public/language/nn-NO/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/nn-NO/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/nn-NO/admin/dashboard.json b/public/language/nn-NO/admin/dashboard.json index 06d9243b62..f82bc64d8d 100644 --- a/public/language/nn-NO/admin/dashboard.json +++ b/public/language/nn-NO/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Emne", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Sidevisningar siste 7 dagar", "page-views-thirty": "Sidevisningar siste 30 dagar", "page-views-last-day": "Sidevisningar siste dag", - "page-views-custom": "Tilpassa sidevisningar", + "page-views-custom": "Custom Range", "page-views-custom-start": "Startdato", "page-views-custom-end": "Sluttdato", "page-views-custom-help": "Vel eit tidsintervall på datoformat YYYY-MM-DD for å sjå sidevisningar. ", diff --git a/public/language/nn-NO/admin/manage/users.json b/public/language/nn-NO/admin/manage/users.json index 9495b75a32..a6a73e6a78 100644 --- a/public/language/nn-NO/admin/manage/users.json +++ b/public/language/nn-NO/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per side", "500-per-page": "500 per side", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Søk etter brukar-ID", "search.uid-placeholder": "Brukar-ID", "search.username": "Søk etter brukarnamn", diff --git a/public/language/nn-NO/admin/menu.json b/public/language/nn-NO/admin/menu.json index 90025d89e0..2855365942 100644 --- a/public/language/nn-NO/admin/menu.json +++ b/public/language/nn-NO/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Loggar", "advanced/errors": "Feil", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Loggførar", "development/info": "Informasjon", diff --git a/public/language/nn-NO/admin/settings/activitypub.json b/public/language/nn-NO/admin/settings/activitypub.json index 016130ebb9..c573484437 100644 --- a/public/language/nn-NO/admin/settings/activitypub.json +++ b/public/language/nn-NO/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/nn-NO/admin/settings/general.json b/public/language/nn-NO/admin/settings/general.json index 2157dd08fb..c32ff58019 100644 --- a/public/language/nn-NO/admin/settings/general.json +++ b/public/language/nn-NO/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Nøkkelord", "keywords-placeholder": "Skriv inn nøkkelord, skilde med komma", - "logo-and-icons": "Logo og ikon", + "logo-and-icons": "Media & Branding", "logo.image": "Bilet-URL for logo", "logo.image-placeholder": "https://din-nettstad.no/logo.png", "logo.upload": "Last opp logo", @@ -35,6 +35,8 @@ "touch-icon.help": "Bruk touch-ikonet for å vise på mobile einingar.", "maskable-icon": "Maskerbart ikon", "maskable-icon.help": "Maskerbare ikon vert brukt for å tilpasse webappen til ulike skjermstorleikar.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Utgåande lenkjer", "outgoing-links.warning-page": "Advarselside for utgåande lenkjer", "search": "Søk", diff --git a/public/language/nn-NO/error.json b/public/language/nn-NO/error.json index fc05cbb0f3..38b0946299 100644 --- a/public/language/nn-NO/error.json +++ b/public/language/nn-NO/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ugyldige data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Ugyldig JSON", "wrong-parameter-type": "Ein verdi av typen %3 var venta for eigenskapen `%1`, men %2 vart mottatt i staden", "required-parameters-missing": "Naudsynt parameter mangla i denne API-kallinga: %1", diff --git a/public/language/nn-NO/world.json b/public/language/nn-NO/world.json index 5d578a5b93..f402724f70 100644 --- a/public/language/nn-NO/world.json +++ b/public/language/nn-NO/world.json @@ -1,6 +1,8 @@ { "name": "Verda", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "På same måte, dersom brukarar frå utsida av dette forumet begynner å følge deg, vil innlegga dine òg begynne å visast på desse appane og nettsidene.", "help.next-generation": "Dette er den neste generasjonen av sosiale medium, begynn å bidra i dag!", - "onboard.title": "Ditt vindauge til fødiverset...", - "onboard.what": "Dette er din personlege kategori som berre består av innhald funne utanfor dette forumet. Om noko blir vist på denne sida, avheng av om du følger dei, eller om innlegget blei delt av nokon du følger.", - "onboard.why": "Det skjer mykje utanfor dette forumet, og ikkje alt er relevant for interessene dine. Difor er det å følge folk den beste måten å signalisere at du ønskjer å sjå meir frå nokon.", - "onboard.how": "I mellomtida kan du klikke på snarvegsknappane øvst for å sjå kva anna dette forumet inneheld, og begynne å oppdage nytt innhald!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/pl/admin/advanced/jobs.json b/public/language/pl/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/pl/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/pl/admin/dashboard.json b/public/language/pl/admin/dashboard.json index d2c710e8ac..11d852ec4d 100644 --- a/public/language/pl/admin/dashboard.json +++ b/public/language/pl/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Tematy", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Ostatnie 7 dni", "page-views-thirty": "Ostatnie 30 dni", "page-views-last-day": "Ostatnie 24 godziny", - "page-views-custom": "Własny zakres dat", + "page-views-custom": "Custom Range", "page-views-custom-start": "Początek zakresu", "page-views-custom-end": "Koniec zakresu", "page-views-custom-help": "Wprowadź zakres dat dla wyświetleń strony, które chcesz zobaczyć. Jeśli nie ma możliwości wyboru daty, obowiązuje format RRRR-MM-DD", diff --git a/public/language/pl/admin/development/info.json b/public/language/pl/admin/development/info.json index 427c0d0c19..2af7ce0489 100644 --- a/public/language/pl/admin/development/info.json +++ b/public/language/pl/admin/development/info.json @@ -8,7 +8,7 @@ "nodejs": "nodejs", "online": "dostępny", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "rss/heap użyty", "system-memory": "pamięć systemowa", "used-memory-process": "Używana pamięć według procesu", "used-memory-os": "Używana pamięć systemowa", diff --git a/public/language/pl/admin/manage/custom-reasons.json b/public/language/pl/admin/manage/custom-reasons.json index 90a2e620af..0ef053cbab 100644 --- a/public/language/pl/admin/manage/custom-reasons.json +++ b/public/language/pl/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", + "title": "Zarządzaj Niestandardowymi Powodami", + "create-reason": "Utwórz powód", + "edit-reason": "Edytuj powód", + "reasons-help": "Powody to predefiniowane wyjaśnienia używane podczas banowania i uciszania użytkowników lub odrzucania postów z kolejki postów.", + "reason-title": "Tytuł", + "reason-type": "Typ", + "reason-body": "Treść", + "reason-all": "Wszystkie", "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "reason-mute": "Ucisz", + "reason-post-queue": "Kolejka Postów", + "reason-type-help": "Typ akcji do jakiej ten powód się stosuje. Jeśli wybrano 'Wszystkie', to ten powód będzie dostępny dla wszystkich typów akcji.", + "custom-reasons-saved": "Niestandardowe powody pomyślnie zapisane", + "delete-reason-confirm-x": "Jesteś pewien, że chcesz usunąć niestandardowy powód o tytule %1?" } \ No newline at end of file diff --git a/public/language/pl/admin/manage/users.json b/public/language/pl/admin/manage/users.json index c33a61b5ff..f1c9bd4c5c 100644 --- a/public/language/pl/admin/manage/users.json +++ b/public/language/pl/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 na stronę", "500-per-page": "500 na stronę", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Po ID użytkownika", "search.uid-placeholder": "Wpisz ID użytkownika, by wyszukać", "search.username": "Po nazwie użytkownika", diff --git a/public/language/pl/admin/menu.json b/public/language/pl/admin/menu.json index 0451a4d9fe..a9b2aea8b2 100644 --- a/public/language/pl/admin/menu.json +++ b/public/language/pl/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logi", "advanced/errors": "Błędy", "advanced/cache": "Pamięć", + "advanced/jobs": "Jobs", "development/logger": "Loger", "development/info": "Informacja", diff --git a/public/language/pl/admin/settings/activitypub.json b/public/language/pl/admin/settings/activitypub.json index 746b544e8c..66f6baa799 100644 --- a/public/language/pl/admin/settings/activitypub.json +++ b/public/language/pl/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/pl/admin/settings/email.json b/public/language/pl/admin/settings/email.json index 06345d7326..b031bfbbc3 100644 --- a/public/language/pl/admin/settings/email.json +++ b/public/language/pl/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "Pooling połączeń sprawia, że NodeBB nie będzie tworzył nowego połączenia dla każdego maila. Ta opcja ma zastosowanie tylko, jeśli transport SMTP jest włączony.", "smtp-transport.allow-self-signed": "Zezwól na własnoręcznie podpisane certyfikaty", "smtp-transport.allow-self-signed-help": "Kiedy włączone będzie przyjmować lokalne i błędne certyfikaty TLS.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "E-mail do testu SMTP wysłany pomyślnie.", "template": "Edytuj szablon e-maila", "template.select": "Wybierz szablon e-maila", "template.revert": "Przywróć oryginalny szablon", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "Ustawienia SMTP do testów", "testing": "Testowanie e-maila", - "testing.success": "Test Email Sent.", + "testing.success": "Testowy e-mail wysłany.", "testing.select": "Wybierz szablon e-maila", "testing.send": "Wyślij testowy e-mail", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" będzie użyty do wysłania testowych e-maili.", + "testing.send-help-smtp": "Transport SMTP jest włączony i będzie używany do wysyłania e-maili.", + "testing.send-help-no-plugin": "Nie ma zainstalowanej wtyczki do wysyłania e-maili, więc jako domyślny zostanie użyty nodemailer.", + "testing.send-help": "Testowy e-mail zostanie wysłany na adres aktualnie zalogowanego użytkownika używając zapisanych ustawień z tej strony.", "subscriptions": "Podsumowania e-mail", "subscriptions.disable": "Wyłącz podsumowania e-maili", "subscriptions.hour": "Godzina podsumowania", diff --git a/public/language/pl/admin/settings/general.json b/public/language/pl/admin/settings/general.json index ed26bb21bf..083be75a77 100644 --- a/public/language/pl/admin/settings/general.json +++ b/public/language/pl/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Opis strony", "keywords": "Słowa kluczowe strony", "keywords-placeholder": "Słowa kluczowe opisujące społeczność, oddzielone przecinkami", - "logo-and-icons": "Logo i ikony strony", + "logo-and-icons": "Media & Branding", "logo.image": "Obraz", "logo.image-placeholder": "Ścieżka do logo, które ma być wyświetlane w nagłówku forum", "logo.upload": "Prześlij", @@ -35,6 +35,8 @@ "touch-icon.help": "Rekomendowana wielkość: 512x512, tylko format PNG. Jeśli nie ustalono ikony dotykowej, użyta zostanie favikona.", "maskable-icon": "Ikona ekranu głównego", "maskable-icon.help": "Rekomendowana wielkość: 512x512, tylko format PNG. Jeśli nie ustalono tej ikony, użyta zostanie ikona dotykowa.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Odnośniki wychodzące", "outgoing-links.warning-page": "Używaj strony ostrzegawczej o odnośnikach wychodzących", "search": "Szukaj", diff --git a/public/language/pl/category.json b/public/language/pl/category.json index ebee64b271..c79df0cb9b 100644 --- a/public/language/pl/category.json +++ b/public/language/pl/category.json @@ -1,8 +1,8 @@ { "category": "Kategoria", "subcategories": "Podkategorie", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "Świat", + "uncategorized.description": "Tematy spoza tego forum. Poglądy i opinie przedstawione tutaj mogą nie odzwierciedlać tych, które reprezentują członkowie tego forum.", "handle.description": "Tę kategorię można śledzić za pośrednictwem %1", "new-topic-button": "Nowy temat", "guest-login-post": "Zaloguj się, aby napisać post", diff --git a/public/language/pl/error.json b/public/language/pl/error.json index 8492ed8ae5..dc28f25f27 100644 --- a/public/language/pl/error.json +++ b/public/language/pl/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Nieprawidłowe dane", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Niewłaściwy JSON", "wrong-parameter-type": "Wartość typu %3 była oczekiwania dla właściwości `%1`, ale %2 został dostarczony", "required-parameters-missing": "Brakowało wymaganych parametrów w tym żądaniu API: %1", diff --git a/public/language/pl/modules.json b/public/language/pl/modules.json index 3022a1ca72..51061aa00f 100644 --- a/public/language/pl/modules.json +++ b/public/language/pl/modules.json @@ -82,7 +82,7 @@ "composer.hide-preview": "Ukryj podgląd", "composer.help": "Pomoc", "composer.user-said-in": "%1 napisał w %2:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [napisał](%2):", "composer.discard": "Na pewno chcesz porzucić ten post?", "composer.submit-and-lock": "Prześlij i zablokuj", "composer.toggle-dropdown": "Przełącz listę rozwijaną", diff --git a/public/language/pl/themes/harmony.json b/public/language/pl/themes/harmony.json index 688bd07df6..c2d4b56d85 100644 --- a/public/language/pl/themes/harmony.json +++ b/public/language/pl/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Styl Harmony", "skins": "Skórki", - "light": "Light", - "dark": "Dark", + "light": "Jasny", + "dark": "Ciemny", "collapse": "Zwiń", "expand": "Rozwiń", "sidebar-toggle": "Przełącz panele boczne", diff --git a/public/language/pl/world.json b/public/language/pl/world.json index 2b7b467d6f..f2bfa77c65 100644 --- a/public/language/pl/world.json +++ b/public/language/pl/world.json @@ -1,12 +1,14 @@ { "name": "Świat", "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", - "recent": "All", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", + "popular-day": "Popularne (Dziś)", + "popular-week": "Popularne (W Tygodniu)", + "popular-month": "Popularne (W Miesiącu)", + "popular-year": "Popularne (W Roku)", + "popular-alltime": "Popularne (Cały Czas)", + "recent": "Wszystkie", "help": "Pomoc", "help.title": "Co to za strona?", @@ -16,10 +18,12 @@ "help.federating": "O ile użytkownicy spoza tego forum zaczną Cię śledzić, to w efekcie Twoje wpisy pojawią się na zewnętrznych stronach i w aplikacjach.", "help.next-generation": "To są media społecznościowe kolejnej generacji, dołącz już dzisiaj!", - "onboard.title": "Twoje okno na fediverse...", - "onboard.what": "Zawartość tej kategorii jest dostowana do Twoich poczynań i zawiera jedynie dane spoza tego forum. Aby się coś tu pojawiło trzeba zacząć śledzić zdalne źródła informacji.", - "onboard.why": "Mnóstwo rzeczy dzieje się poza tym forum ale niekoniecznie zgodnych z Twoimi zainteresowaniami. Dlatego śledzenie konkretnych użytkowników jest dobrą metodą aby uzyskać więcej zawartości przez nich dodawanych.", - "onboard.how": "W międzyczasie możesz użyć przycisków skrótów na górze aby przekonać się jak forum jest powiązane a okaże się, że zapewnia wiele dodatkowych treści!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Znajdź kategorię...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/pt-BR/admin/advanced/jobs.json b/public/language/pt-BR/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/pt-BR/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/pt-BR/admin/dashboard.json b/public/language/pt-BR/admin/dashboard.json index 61a2a61f03..4aaf717148 100644 --- a/public/language/pt-BR/admin/dashboard.json +++ b/public/language/pt-BR/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Tópicos", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Últimos 7 Dias", "page-views-thirty": "Últimos 30 Dias", "page-views-last-day": "Últimas 24 horas", - "page-views-custom": "Intervalo de Data Personalizado", + "page-views-custom": "Custom Range", "page-views-custom-start": "Ínicio do Intervalo", "page-views-custom-end": "Fim do Intervalo", "page-views-custom-help": "Entre com um intervalo de data de visualizações de página que gostaria de ver. Se nenhum selecionador de data estiver disponível, o formato aceito é AAAA-MM-DD", diff --git a/public/language/pt-BR/admin/manage/users.json b/public/language/pt-BR/admin/manage/users.json index 8815efe688..8f2b6337e4 100644 --- a/public/language/pt-BR/admin/manage/users.json +++ b/public/language/pt-BR/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 por página", "500-per-page": "500 por página", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Por ID de usuário", "search.uid-placeholder": "Digite o ID do usuário para pesquisar", "search.username": "Por Nome de Usuário", diff --git a/public/language/pt-BR/admin/menu.json b/public/language/pt-BR/admin/menu.json index ed5e9de3f3..dfe31874f0 100644 --- a/public/language/pt-BR/admin/menu.json +++ b/public/language/pt-BR/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Erros", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Informação", diff --git a/public/language/pt-BR/admin/settings/activitypub.json b/public/language/pt-BR/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/pt-BR/admin/settings/activitypub.json +++ b/public/language/pt-BR/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/pt-BR/admin/settings/general.json b/public/language/pt-BR/admin/settings/general.json index d59c71f9f5..c96b724a56 100644 --- a/public/language/pt-BR/admin/settings/general.json +++ b/public/language/pt-BR/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Palavras-chave do Site", "keywords-placeholder": "Palavras-chave descrevendo sua comunidade, separadas por vírgula", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Imagem", "logo.image-placeholder": "Caminho de URL do logotipo para mostrar no cabeçalho do fórum", "logo.upload": "Enviar", @@ -35,6 +35,8 @@ "touch-icon.help": "Tamanho e formato recomendados: 512x512, somente formato PNG. Se nenhum ícone para touch for especificado, o NodeBB usará o seu próprio favicon.", "maskable-icon": "Ícone Mascarável (de Tela Inicial)", "maskable-icon.help": "Tamanho e formato recomendados: 512x512, somente formato PNG. Se nenhum ícone mascarável for especificado, o NodeBB usará o seu próprio Ícone para Touch.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Links Externos", "outgoing-links.warning-page": "Habilitar Página de Aviso de Links Externos", "search": "Search", diff --git a/public/language/pt-BR/error.json b/public/language/pt-BR/error.json index c66978d1a2..58da962dcc 100644 --- a/public/language/pt-BR/error.json +++ b/public/language/pt-BR/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Dados Inválidos", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "JSON Inválido", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/pt-BR/world.json b/public/language/pt-BR/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/pt-BR/world.json +++ b/public/language/pt-BR/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/pt-PT/admin/advanced/jobs.json b/public/language/pt-PT/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/pt-PT/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/pt-PT/admin/dashboard.json b/public/language/pt-PT/admin/dashboard.json index b08b0d8de7..1db0fd47de 100644 --- a/public/language/pt-PT/admin/dashboard.json +++ b/public/language/pt-PT/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Tópicos", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Últimos 7 Dias", "page-views-thirty": "Últimos 30 Dias", "page-views-last-day": "Últimas 24 horas", - "page-views-custom": "Intervalo Personalizado", + "page-views-custom": "Custom Range", "page-views-custom-start": "Início do Intervalo", "page-views-custom-end": "Fim do Intervalo", "page-views-custom-help": "Insere um intervalo entre datas de visualizações de página que gostarias de visualizar. Se o selecionador de datas não estiver disponível, o formato aceitável é AAAA-MM-DD", diff --git a/public/language/pt-PT/admin/manage/users.json b/public/language/pt-PT/admin/manage/users.json index d941d4c13e..ba5fb16a59 100644 --- a/public/language/pt-PT/admin/manage/users.json +++ b/public/language/pt-PT/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 por página", "500-per-page": "500 por página", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Por ID de Utilizador", "search.uid-placeholder": "Digita um ID de utilizador para procurar", "search.username": "Por Nome de Utilizador", diff --git a/public/language/pt-PT/admin/menu.json b/public/language/pt-PT/admin/menu.json index 44e1e12814..6ac9286fed 100644 --- a/public/language/pt-PT/admin/menu.json +++ b/public/language/pt-PT/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Eventos", "advanced/errors": "Erros", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Informação", diff --git a/public/language/pt-PT/admin/settings/activitypub.json b/public/language/pt-PT/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/pt-PT/admin/settings/activitypub.json +++ b/public/language/pt-PT/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/pt-PT/admin/settings/general.json b/public/language/pt-PT/admin/settings/general.json index 8e7e464640..394753a971 100644 --- a/public/language/pt-PT/admin/settings/general.json +++ b/public/language/pt-PT/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Palavras-chave do Site", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Imagem", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Enviar", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Links Externos", "outgoing-links.warning-page": "Utilizar a página de aviso para links externos", "search": "Search", diff --git a/public/language/pt-PT/error.json b/public/language/pt-PT/error.json index e8d1af8063..23331c928d 100644 --- a/public/language/pt-PT/error.json +++ b/public/language/pt-PT/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Dados inválidos", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "JSON inválido", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/pt-PT/world.json b/public/language/pt-PT/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/pt-PT/world.json +++ b/public/language/pt-PT/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/ro/admin/advanced/jobs.json b/public/language/ro/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ro/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ro/admin/dashboard.json b/public/language/ro/admin/dashboard.json index e431c275b6..e81c07ce09 100644 --- a/public/language/ro/admin/dashboard.json +++ b/public/language/ro/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/ro/admin/manage/users.json b/public/language/ro/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/ro/admin/manage/users.json +++ b/public/language/ro/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/ro/admin/menu.json b/public/language/ro/admin/menu.json index 6a35fa9a7f..28daaac97a 100644 --- a/public/language/ro/admin/menu.json +++ b/public/language/ro/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/ro/admin/settings/activitypub.json b/public/language/ro/admin/settings/activitypub.json index 79dfbd9e30..f4d9a3d629 100644 --- a/public/language/ro/admin/settings/activitypub.json +++ b/public/language/ro/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ro/admin/settings/general.json b/public/language/ro/admin/settings/general.json index ebebb10fa5..3d4dd933d3 100644 --- a/public/language/ro/admin/settings/general.json +++ b/public/language/ro/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Descrierea site-ului", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/ro/error.json b/public/language/ro/error.json index 061f30a03c..98f21dce51 100644 --- a/public/language/ro/error.json +++ b/public/language/ro/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Date invalide", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/ro/world.json b/public/language/ro/world.json index 1cf69ff755..69f9b8e5d0 100644 --- a/public/language/ro/world.json +++ b/public/language/ro/world.json @@ -1,6 +1,8 @@ { "name": "Lumea", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "De asemenea, dacă utilizatori din afara acestui forum încep să te urmărească, atunci postările tale vor începe să apară și pe acele aplicații și site-uri web.", "help.next-generation": "Aceasta este următoarea generație de social media, începe să contribui chiar azi!", - "onboard.title": "Fereastra ta către fedivers...", - "onboard.what": "Aceasta este categoria ta personalizată, formată doar din conținut găsit în afara acestui forum. Afișarea unui element pe această pagină depinde de dacă îl urmărești sau dacă postarea respectivă a fost distribuită de cineva pe care îl urmărești.", - "onboard.why": "Se întâmplă multe lucruri în afara acestui forum și nu toate sunt relevante pentru interesele tale. De aceea, urmărirea oamenilor este cea mai bună modalitate de a semnala că vrei să vezi mai multe de la cineva.", - "onboard.how": "Între timp, puteți da clic pe butoanele de comandă rapidă din partea de sus pentru a vedea ce mai știe acest forum și pentru a începe să descoperiți conținut nou!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/ru/admin/advanced/jobs.json b/public/language/ru/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ru/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ru/admin/dashboard.json b/public/language/ru/admin/dashboard.json index 239bdcdeb5..87123fd1ec 100644 --- a/public/language/ru/admin/dashboard.json +++ b/public/language/ru/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Тем", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "За 7 дней", "page-views-thirty": "За 30 дней", "page-views-last-day": "За 24 часа", - "page-views-custom": "Другой диапазон дат", + "page-views-custom": "Custom Range", "page-views-custom-start": "Начало", "page-views-custom-end": "Конец", "page-views-custom-help": "Укажите начало и конец периода, за который вы хотите получить данные о просмотрах. Если выбор даты не доступен, то вы можете указать дату в формате ГГГГ-ММ-ДД ", diff --git a/public/language/ru/admin/manage/users.json b/public/language/ru/admin/manage/users.json index fabb420e9b..35fd0cbfa0 100644 --- a/public/language/ru/admin/manage/users.json +++ b/public/language/ru/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 на страницу", "500-per-page": "500 на страницу", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "По ID пользователя", "search.uid-placeholder": "Введите ID пользователя для поиска", "search.username": "По имени пользователя", diff --git a/public/language/ru/admin/menu.json b/public/language/ru/admin/menu.json index 16a13d0976..49aafa05bf 100644 --- a/public/language/ru/admin/menu.json +++ b/public/language/ru/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Системный журнал", "advanced/errors": "Журнал ошибок", "advanced/cache": "Кэш", + "advanced/jobs": "Jobs", "development/logger": "Отладочный журнал", "development/info": "Сведения о системе", diff --git a/public/language/ru/admin/settings/activitypub.json b/public/language/ru/admin/settings/activitypub.json index be8f21ea1a..11d3ce79b5 100644 --- a/public/language/ru/admin/settings/activitypub.json +++ b/public/language/ru/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ru/admin/settings/general.json b/public/language/ru/admin/settings/general.json index 21aceec945..cfeaca388e 100644 --- a/public/language/ru/admin/settings/general.json +++ b/public/language/ru/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Ключевые слова для сайта", "keywords-placeholder": "Укажите через запятую ключевые слова, описывающие ваше сообщество", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Логотип в шапке сайта", "logo.image-placeholder": "Путь к файлу логотипа ", "logo.upload": "Загрузить", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Внешние ссылки", "outgoing-links.warning-page": "Предупреждать, когда пользователь переходит по внешним ссылкам", "search": "Поиск", diff --git a/public/language/ru/error.json b/public/language/ru/error.json index 2b65778b21..bb0f988115 100644 --- a/public/language/ru/error.json +++ b/public/language/ru/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Неверные данные", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Некорректный JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Обязательные параметры отсутствуют в API запросе: %1", diff --git a/public/language/ru/topic.json b/public/language/ru/topic.json index 8020fa99fd..cdbd32efc5 100644 --- a/public/language/ru/topic.json +++ b/public/language/ru/topic.json @@ -15,7 +15,7 @@ "replies-to-this-post": "%1 ответов", "one-reply-to-this-post": "1 ответ", "last-reply-time": "Последний ответ", - "reply-options": "Reply options", + "reply-options": "Варианты ответа", "reply-as-topic": "Ответить, создав новую тему", "guest-login-reply": "Авторизуйтесь, чтобы ответить", "login-to-view": "Авторизуйтесь, чтобы просмотреть", @@ -36,7 +36,7 @@ "pinned": "Прикреплена", "pinned-with-expiry": "Закреплен до %1", "scheduled": "Запланировано", - "deleted": "Deleted", + "deleted": "Удалён", "moved": "Перенесена", "moved-from": "Перенесено с %1", "copy-code": "Copy Code", @@ -145,7 +145,7 @@ "loading-more-posts": "Загружаем больше сообщений", "move-topic": "Перенести тему", "move-topics": "Перенести темы", - "crosspost-topic": "Cross-post Topic", + "crosspost-topic": "Дублировать тему", "move-post": "Перенести сообщение", "post-moved": "Сообщение перенесено!", "fork-topic": "Создать дополнительную ветвь дискуссии", @@ -168,7 +168,7 @@ "move-topic-instruction": "Select the target category and then click move", "change-owner-instruction": "Нажмите на сообщения, которые вы хотите присвоить другому пользователю", "manage-editors-instruction": "Manage the users who can edit this post below.", - "crossposts.instructions": "Select one or more categories to cross-post to. Topic(s) will be accessible from the original category and all cross-posted categories.", + "crossposts.instructions": "Укажите дополнительные категории для этой темы. Она будет видна во всех выбранных разделах, исходная категория сохранится.", "crossposts.listing": "This topic has been cross-posted to the following local categories:", "crossposts.none": "This topic has not been cross-posted to any additional categories", "composer.title-placeholder": "Введите название темы...", @@ -228,14 +228,14 @@ "post-quick-create": "Quick post", "navigator.index": "Сообщений %1 от %2", "navigator.unread": "%1 непрочитано", - "upvote-post": "Upvote post", - "downvote-post": "Downvote post", + "upvote-post": "Полезно", + "downvote-post": "Не полезно", "post-tools": "Post tools", "unread-posts-link": "Unread posts link", "thumb-image": "Topic thumbnail image", - "announcers": "Shares", - "announcers-x": "Shares (%1)", - "guest-cta.title": "Hello! It looks like you're interested in this conversation, but you don't have an account yet.", - "guest-cta.message": "Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.", - "guest-cta.closing": "With your input, this post could be even better 💗" + "announcers": "Поделиться", + "announcers-x": "Поделиться (%1)", + "guest-cta.title": "Здравствуйте! Похоже, вам интересна эта беседа, но у вас пока нет учетной записи.", + "guest-cta.message": "Вы устали просматривать одни и те же посты каждый раз, когда заходите на сайт? После регистрации, вам не придётся искать обсуждения в которых вы принимали участие, настройте уведомления о новых сообщениях так как вам это удобно (по электронной почте или уведомлением). У вас появится возможность сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.", + "guest-cta.closing": "С вашими комментариями этот пост может стать ещё лучше 💗" } \ No newline at end of file diff --git a/public/language/ru/world.json b/public/language/ru/world.json index 6a99c712a2..56688fcbda 100644 --- a/public/language/ru/world.json +++ b/public/language/ru/world.json @@ -1,6 +1,8 @@ { "name": "Мир", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Аналогично, если пользователи за пределами этого форума начнут подписываться на вас, то ваши сообщения также начнут появляться в этих приложениях и на этих сайтах.", "help.next-generation": "Это новое поколение социальных сетей, начните вносить свой вклад уже сегодня!", - "onboard.title": "Ваше окно в мир fediverse...", - "onboard.what": "Это ваша персонализированная категория, состоящая только из контента, найденного за пределами этого форума. Появится ли что-то на этой странице, зависит от того, подписаны ли вы на них, или же этот пост был опубликован кем-то, на кого вы подписаны.", - "onboard.why": "За пределами этого форума происходит много всего, и не все из этого соответствует вашим интересам. Вот почему подписка на людей — лучший способ подать сигнал о том, что вы хотите видеть больше от кого-то.", - "onboard.how": "А пока вы можете нажать на кнопки быстрого доступа вверху, чтобы узнать, что еще известно на этом форуме, и начать открывать для себя новый контент!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/rw/admin/advanced/jobs.json b/public/language/rw/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/rw/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/rw/admin/dashboard.json b/public/language/rw/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/rw/admin/dashboard.json +++ b/public/language/rw/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/rw/admin/manage/users.json b/public/language/rw/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/rw/admin/manage/users.json +++ b/public/language/rw/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/rw/admin/menu.json b/public/language/rw/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/rw/admin/menu.json +++ b/public/language/rw/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/rw/admin/settings/activitypub.json b/public/language/rw/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/rw/admin/settings/activitypub.json +++ b/public/language/rw/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/rw/admin/settings/general.json b/public/language/rw/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/rw/admin/settings/general.json +++ b/public/language/rw/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/rw/error.json b/public/language/rw/error.json index db5be26f51..6708efbb44 100644 --- a/public/language/rw/error.json +++ b/public/language/rw/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ibyashyizwemo Ntibyemewe", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/rw/world.json b/public/language/rw/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/rw/world.json +++ b/public/language/rw/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sc/admin/advanced/jobs.json b/public/language/sc/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sc/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sc/admin/dashboard.json b/public/language/sc/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/sc/admin/dashboard.json +++ b/public/language/sc/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/sc/admin/manage/users.json b/public/language/sc/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/sc/admin/manage/users.json +++ b/public/language/sc/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/sc/admin/menu.json b/public/language/sc/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/sc/admin/menu.json +++ b/public/language/sc/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/sc/admin/settings/activitypub.json b/public/language/sc/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sc/admin/settings/activitypub.json +++ b/public/language/sc/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sc/admin/settings/general.json b/public/language/sc/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/sc/admin/settings/general.json +++ b/public/language/sc/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/sc/error.json b/public/language/sc/error.json index 10c9469a66..e2d479d164 100644 --- a/public/language/sc/error.json +++ b/public/language/sc/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Invalid Data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/sc/world.json b/public/language/sc/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sc/world.json +++ b/public/language/sc/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sk/admin/advanced/jobs.json b/public/language/sk/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sk/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sk/admin/dashboard.json b/public/language/sk/admin/dashboard.json index 4c8fffc878..22458948f7 100644 --- a/public/language/sk/admin/dashboard.json +++ b/public/language/sk/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Témy", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Posledných 7 dní", "page-views-thirty": "Posledných 30 dní", "page-views-last-day": "Posledných 24 hodín", - "page-views-custom": "Podľa rozsahu dátumu", + "page-views-custom": "Custom Range", "page-views-custom-start": "Začiatok rozsahu", "page-views-custom-end": "Koniec rozsahu", "page-views-custom-help": "Zadajte rozsah obdobia zobrazenia stránok, ktoré chcete vidieť. Ak nie je obdobie nastavené, predvolený formát je YYYY-MM-DD", diff --git a/public/language/sk/admin/manage/users.json b/public/language/sk/admin/manage/users.json index 4cee2084a2..d77abce887 100644 --- a/public/language/sk/admin/manage/users.json +++ b/public/language/sk/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Podľa ID používateľa", "search.uid-placeholder": "Pre hľadanie, zadajte ID používateľa", "search.username": "Podľa mena používateľa", diff --git a/public/language/sk/admin/menu.json b/public/language/sk/admin/menu.json index e037b5d4f5..1dc4bc8d69 100644 --- a/public/language/sk/admin/menu.json +++ b/public/language/sk/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Protokoly", "advanced/errors": "Chyby", "advanced/cache": "Medzipamäť", + "advanced/jobs": "Jobs", "development/logger": "Protokolár", "development/info": "Informácie", diff --git a/public/language/sk/admin/settings/activitypub.json b/public/language/sk/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sk/admin/settings/activitypub.json +++ b/public/language/sk/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sk/admin/settings/general.json b/public/language/sk/admin/settings/general.json index 2dfddf133e..2223015b5a 100644 --- a/public/language/sk/admin/settings/general.json +++ b/public/language/sk/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Kľúčové slová pre stránky", "keywords-placeholder": "Kľúčové slová popisujúce Vašu komunitu, oddelené čiarkou", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Obrázok", "logo.image-placeholder": "Cesta k logu, aby mohlo byť zobrazené v hlavičke fóra", "logo.upload": "Nahrať", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Odchádzajúce odkazy", "outgoing-links.warning-page": "Použiť stránku s upozornením pri odchádzajúcich odkazoch", "search": "Search", diff --git a/public/language/sk/error.json b/public/language/sk/error.json index cfee6f95e2..bb14e6f77d 100644 --- a/public/language/sk/error.json +++ b/public/language/sk/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Nesprávne údaje", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Neplatné JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/sk/world.json b/public/language/sk/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sk/world.json +++ b/public/language/sk/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sl/admin/advanced/jobs.json b/public/language/sl/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sl/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sl/admin/dashboard.json b/public/language/sl/admin/dashboard.json index 6584673051..7209c4b083 100644 --- a/public/language/sl/admin/dashboard.json +++ b/public/language/sl/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Teme", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Zadnjih 7 dni", "page-views-thirty": "Zadnjih 30 dni", "page-views-last-day": "Zadnjih 24 ur", - "page-views-custom": "Časovno obdobje po meri", + "page-views-custom": "Custom Range", "page-views-custom-start": "Začetek obdobja", "page-views-custom-end": "Konec obdobja", "page-views-custom-help": "Vnesite časovno obdobje ogledov strani, ki bi si jih radi ogledali. Če izbirnik datumov ni na voljo, je sprejeta oblika LLLL-MM-DD", diff --git a/public/language/sl/admin/manage/users.json b/public/language/sl/admin/manage/users.json index 1f1a7876ce..aad472e70d 100644 --- a/public/language/sl/admin/manage/users.json +++ b/public/language/sl/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 na stran", "500-per-page": "500 na stran", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Po ID uporabnika", "search.uid-placeholder": "Za iskanje vnesite ID uporabnika", "search.username": "Po imenu uporabnika", diff --git a/public/language/sl/admin/menu.json b/public/language/sl/admin/menu.json index 71bf60ee54..02882122cf 100644 --- a/public/language/sl/admin/menu.json +++ b/public/language/sl/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Prijave", "advanced/errors": "Napake", "advanced/cache": "Predpomnilnik", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/sl/admin/settings/activitypub.json b/public/language/sl/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sl/admin/settings/activitypub.json +++ b/public/language/sl/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sl/admin/settings/general.json b/public/language/sl/admin/settings/general.json index ea11d557c7..fec7da1605 100644 --- a/public/language/sl/admin/settings/general.json +++ b/public/language/sl/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Ključne besede spletnega mesta", "keywords-placeholder": "Ključne besede, ki opisujejo vašo skupnost, ločene z vejicami", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Slika", "logo.image-placeholder": "Pot do logotipa za prikaz v glavi foruma", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Odhodne povezave", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Išči", diff --git a/public/language/sl/error.json b/public/language/sl/error.json index 6ef3a59feb..ce9a320ffe 100644 --- a/public/language/sl/error.json +++ b/public/language/sl/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Napačni podatki", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Invalid JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/sl/world.json b/public/language/sl/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sl/world.json +++ b/public/language/sl/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sq-AL/admin/advanced/jobs.json b/public/language/sq-AL/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sq-AL/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sq-AL/admin/dashboard.json b/public/language/sq-AL/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/sq-AL/admin/dashboard.json +++ b/public/language/sq-AL/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/sq-AL/admin/manage/users.json b/public/language/sq-AL/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/sq-AL/admin/manage/users.json +++ b/public/language/sq-AL/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/sq-AL/admin/menu.json b/public/language/sq-AL/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/sq-AL/admin/menu.json +++ b/public/language/sq-AL/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/sq-AL/admin/settings/activitypub.json b/public/language/sq-AL/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sq-AL/admin/settings/activitypub.json +++ b/public/language/sq-AL/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sq-AL/admin/settings/general.json b/public/language/sq-AL/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/sq-AL/admin/settings/general.json +++ b/public/language/sq-AL/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/sq-AL/error.json b/public/language/sq-AL/error.json index a750e9d3e7..ead88b572c 100644 --- a/public/language/sq-AL/error.json +++ b/public/language/sq-AL/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Të dhëna të pavlefshme", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "JSON i pavlefshëm", "wrong-parameter-type": "Pritej një vlerë e tipit %3 për vetinë '%1', por në vend të saj u mor %2", "required-parameters-missing": "Parametrat e kërkuar mungonin në këtë API: %1", diff --git a/public/language/sq-AL/world.json b/public/language/sq-AL/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sq-AL/world.json +++ b/public/language/sq-AL/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sr/admin/advanced/jobs.json b/public/language/sr/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sr/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sr/admin/dashboard.json b/public/language/sr/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/sr/admin/dashboard.json +++ b/public/language/sr/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/sr/admin/manage/users.json b/public/language/sr/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/sr/admin/manage/users.json +++ b/public/language/sr/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/sr/admin/menu.json b/public/language/sr/admin/menu.json index bfa8e261a2..39bdd966de 100644 --- a/public/language/sr/admin/menu.json +++ b/public/language/sr/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Izveštaji", "advanced/errors": "Greške", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Loger", "development/info": "Info", diff --git a/public/language/sr/admin/settings/activitypub.json b/public/language/sr/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sr/admin/settings/activitypub.json +++ b/public/language/sr/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sr/admin/settings/general.json b/public/language/sr/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/sr/admin/settings/general.json +++ b/public/language/sr/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/sr/error.json b/public/language/sr/error.json index 99766da009..9c50f92230 100644 --- a/public/language/sr/error.json +++ b/public/language/sr/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Неисправни подаци", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Неважећи JSON", "wrong-parameter-type": "Очекивана је вредност типа %3 за својство %1, али је уместо тога примљен %2", "required-parameters-missing": "Недостајали су обавезни параметри у овом API позиву: %1", diff --git a/public/language/sr/world.json b/public/language/sr/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sr/world.json +++ b/public/language/sr/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/sv/admin/advanced/jobs.json b/public/language/sv/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/sv/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/sv/admin/dashboard.json b/public/language/sv/admin/dashboard.json index a35775fdce..1cec2284e7 100644 --- a/public/language/sv/admin/dashboard.json +++ b/public/language/sv/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Topics", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Last 7 Days", "page-views-thirty": "Last 30 Days", "page-views-last-day": "Last 24 hours", - "page-views-custom": "Custom Date Range", + "page-views-custom": "Custom Range", "page-views-custom-start": "Range Start", "page-views-custom-end": "Range End", "page-views-custom-help": "Enter a date range of page views you would like to view. If no date picker is available, the accepted format is YYYY-MM-DD", diff --git a/public/language/sv/admin/manage/users.json b/public/language/sv/admin/manage/users.json index b669dcca11..9b46ea0cc2 100644 --- a/public/language/sv/admin/manage/users.json +++ b/public/language/sv/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "By User ID", "search.uid-placeholder": "Enter a user ID to search", "search.username": "By User Name", diff --git a/public/language/sv/admin/menu.json b/public/language/sv/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/sv/admin/menu.json +++ b/public/language/sv/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/sv/admin/settings/activitypub.json b/public/language/sv/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/sv/admin/settings/activitypub.json +++ b/public/language/sv/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/sv/admin/settings/general.json b/public/language/sv/admin/settings/general.json index d56c819745..0ee921d831 100644 --- a/public/language/sv/admin/settings/general.json +++ b/public/language/sv/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/sv/error.json b/public/language/sv/error.json index 6508d38419..cda7701e74 100644 --- a/public/language/sv/error.json +++ b/public/language/sv/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Ogiltig data", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Ogiltig JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/sv/world.json b/public/language/sv/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/sv/world.json +++ b/public/language/sv/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/th/admin/advanced/jobs.json b/public/language/th/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/th/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/th/admin/dashboard.json b/public/language/th/admin/dashboard.json index 0510e3d5f7..e41d530704 100644 --- a/public/language/th/admin/dashboard.json +++ b/public/language/th/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "จำนวนกระทู้", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "7 วันล่าสุด", "page-views-thirty": "30 วันล่าสุด", "page-views-last-day": "24 ชั่วโมงที่แล้ว", - "page-views-custom": "ช่วงเวลาที่กำหนดเอง", + "page-views-custom": "Custom Range", "page-views-custom-start": "ช่วงเวลาเริ่มต้น", "page-views-custom-end": "ช่วงเวลาสิ้นสุด", "page-views-custom-help": "ใส่ช่วงวันที่ที่คุณต้องการดูค่า ถ้ากดเลือกวันที่ไม่ได้ ให้กรอกวันที่ในรูปแบบ YYYY-MM-DD", diff --git a/public/language/th/admin/manage/users.json b/public/language/th/admin/manage/users.json index 1c40a795b6..c775c4ea3e 100644 --- a/public/language/th/admin/manage/users.json +++ b/public/language/th/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 รายการต่อหน้า", "500-per-page": "500 รายการต่อหน้า", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "ตามรหัสผู้ใช้", "search.uid-placeholder": "ป้อนหมายเลขผู้ใช้เพื่อค้นหา", "search.username": "โดยชื่อผู้ใช้งาน", diff --git a/public/language/th/admin/menu.json b/public/language/th/admin/menu.json index 9a2566141e..d55f62045e 100644 --- a/public/language/th/admin/menu.json +++ b/public/language/th/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Logs", "advanced/errors": "Errors", "advanced/cache": "Cache", + "advanced/jobs": "Jobs", "development/logger": "Logger", "development/info": "Info", diff --git a/public/language/th/admin/settings/activitypub.json b/public/language/th/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/th/admin/settings/activitypub.json +++ b/public/language/th/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/th/admin/settings/general.json b/public/language/th/admin/settings/general.json index a0f6cc7655..85299636dd 100644 --- a/public/language/th/admin/settings/general.json +++ b/public/language/th/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Keywords", "keywords-placeholder": "Keywords describing your community, comma-separated", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Image", "logo.image-placeholder": "Path to a logo to display on forum header", "logo.upload": "Upload", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Outgoing Links", "outgoing-links.warning-page": "Use Outgoing Links Warning Page", "search": "Search", diff --git a/public/language/th/error.json b/public/language/th/error.json index 207ff70448..41f40f9770 100644 --- a/public/language/th/error.json +++ b/public/language/th/error.json @@ -1,5 +1,6 @@ { "invalid-data": "ข้อมูลไม่ถูกต้อง", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "รูปแบบ JSON ไม่ถูกต้อง", "wrong-parameter-type": "ต้องการข้อมูลประเภท %3 สำหรับค่า `%1` แต่ได้รับค่า %2 แทน", "required-parameters-missing": "ขาดพารามิเตอร์ที่จำเป็นต่อการเรียก API นี้: %1", diff --git a/public/language/th/world.json b/public/language/th/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/th/world.json +++ b/public/language/th/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/tr/admin/advanced/jobs.json b/public/language/tr/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/tr/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/tr/admin/dashboard.json b/public/language/tr/admin/dashboard.json index a780d95af9..274d5ed319 100644 --- a/public/language/tr/admin/dashboard.json +++ b/public/language/tr/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Başlıklar", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Son 7 Gün", "page-views-thirty": "Son 30 Gün", "page-views-last-day": "Son 24 saat", - "page-views-custom": "Özel Tarih Aralığı", + "page-views-custom": "Custom Range", "page-views-custom-start": "Başlangıç Tarihi", "page-views-custom-end": "Bitiş Tarihi", "page-views-custom-help": "İncelemek istediğiniz sayfa gösterim sayıları için bir tarih aralığı girin. Tarih seçeceğiniz panel görünmezse, kabul edilebilir format YYYY-AA-GG'dir.", diff --git a/public/language/tr/admin/manage/users.json b/public/language/tr/admin/manage/users.json index 452e2a91bf..fb3910000f 100644 --- a/public/language/tr/admin/manage/users.json +++ b/public/language/tr/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "Sayfa başına 250", "500-per-page": "Sayfa başına 500", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "Kullanıcı Kimliğiyle", "search.uid-placeholder": "Aramak için bir kullanıcı kimliği girin", "search.username": "Kullanıcı Adına Göre", diff --git a/public/language/tr/admin/menu.json b/public/language/tr/admin/menu.json index 4d82d9828d..f7e3fda41a 100644 --- a/public/language/tr/admin/menu.json +++ b/public/language/tr/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Kayıtlar", "advanced/errors": "Hatalar", "advanced/cache": "Önbellek", + "advanced/jobs": "Jobs", "development/logger": "Kaydedici", "development/info": "bilgi", diff --git a/public/language/tr/admin/settings/activitypub.json b/public/language/tr/admin/settings/activitypub.json index 0486870db1..707c485bf2 100644 --- a/public/language/tr/admin/settings/activitypub.json +++ b/public/language/tr/admin/settings/activitypub.json @@ -1,7 +1,7 @@ { "intro-lead": "What is Federation?", "intro-body": "NodeBB is able to communicate with other NodeBB instances that support it. This is achieved through a protocol called ActivityPub. If enabled, NodeBB will also be able to communicate with other apps and websites that use ActivityPub (e.g. Mastodon, Peertube, etc.)", - "general": "General", + "general": "Genel", "pruning": "Content Pruning", "content-pruning": "Days to keep remote content", "content-pruning-help": "Note that remote content that has received engagement (a reply or a upvote/downvote) will be preserved. (0 for disabled)", @@ -12,22 +12,22 @@ "allowLoopback": "Allow loopback processing", "allowLoopback-help": "Useful for debugging purposes only. You should probably leave this disabled.", - "probe": "Open in App", + "probe": "App ile aç", "probe-enabled": "Try to open ActivityPub-enabled resources in NodeBB", "probe-enabled-help": "If enabled, NodeBB will check every external link for an ActivityPub equivalent, and load it in NodeBB instead.", "probe-timeout": "Lookup Timeout (milliseconds)", "probe-timeout-help": "(Default: 2000) If the lookup query does not receive a response within the set timeframe, will send the user to the link directly instead. Adjust this number higher if sites are responding slowly and you wish to give extra time.", - "rules": "Categorization", + "rules": "Kategorileştirme", "rules-intro": "Content discovered via ActivityPub can be automatically categorized based on certain rules (e.g. hashtag)", "rules.modal.title": "How it works", "rules.modal.instructions": "Any incoming content is checked against these categorization rules, and matching content is automatically moved into the category of choice.

N.B. Content that is already categorized (i.e. in a remote category) will not pass through these rules.", - "rules.add": "Add New Rule", + "rules.add": "Yeni Kural Ekle", "rules.help-hashtag": "Topics containing this case-insensitive hashtag will match. Do not enter the # symbol", "rules.help-user": "Topics created by the entered user will match. Enter a handle or full ID (e.g. bob@example.org or https://example.org/users/bob.", - "rules.type": "Type", - "rules.value": "Value", - "rules.cid": "Category", + "rules.type": "Tür", + "rules.value": "Değer", + "rules.cid": "Kategori", "relays": "Relays", "relays.intro": "A relay improves discovery of content to and from your NodeBB. Subscribing to a relay means content received by the relay is forwarded here, and content posted here is syndicated outward by the relay.", @@ -35,12 +35,12 @@ "relays.litepub": "NodeBB follows the LitePub-style relay standard. The URL you enter here should end with /actor.", "relays.add": "Add New Relay", "relays.relay": "Relay", - "relays.state": "State", - "relays.state-0": "Pending", - "relays.state-1": "Receiving only", - "relays.state-2": "Active", + "relays.state": "Durum", + "relays.state-0": "Beklemede", + "relays.state-1": "Sadece al", + "relays.state-2": "Etkin", - "server-filtering": "Filtering", + "server-filtering": "Filtreleme", "count": "This NodeBB is currently aware of %1 server(s)", "server.filter-help": "Specify servers you would like to bar from federating with your NodeBB. Alternatively, you may opt to selectively allow federation with specific servers, instead. Both options are supported, although they are mutually exclusive.", "server.filter-help-hostname": "Enter just the instance hostname below (e.g. example.org), separated by line breaks.", @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/tr/admin/settings/general.json b/public/language/tr/admin/settings/general.json index e553bcdf41..27df764c91 100644 --- a/public/language/tr/admin/settings/general.json +++ b/public/language/tr/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Site Anahtar Kelimeler", "keywords-placeholder": "Topluluğunuzu tanımlayan anahtar kelimeler, virgülle-ayrılmış", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Görsel", "logo.image-placeholder": "Forum başlığında görüntülenecek bir logo yolu", "logo.upload": "Yükle", @@ -35,6 +35,8 @@ "touch-icon.help": "Önerilen Boyut: 512x512. Önerilen format: PNG. Simge belirtilmezse varsayılan olarak favicon kullanılır.", "maskable-icon": "Maskelenebilir (Ana Ekran) Simgesi", "maskable-icon.help": "Önerilen boyut ve format: 512x512, PNG formatı. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Harici Bağlantılar", "outgoing-links.warning-page": "Dışarı giden bağlantılar için uyarı sayfası kullan", "search": "Arama", diff --git a/public/language/tr/error.json b/public/language/tr/error.json index 7ccad228c5..f6eeebcb03 100644 --- a/public/language/tr/error.json +++ b/public/language/tr/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Geçersiz Veri", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Geçersiz JSON", "wrong-parameter-type": "\"%1\" özelliği için %3 türünde bir değer bekleniyordu, ancak bunun yerine %2 alındı", "required-parameters-missing": "Bu API çağrısında gerekli parametreler eksikti: %1", diff --git a/public/language/tr/world.json b/public/language/tr/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/tr/world.json +++ b/public/language/tr/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/uk/admin/advanced/jobs.json b/public/language/uk/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/uk/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/uk/admin/dashboard.json b/public/language/uk/admin/dashboard.json index faf3ce3665..eb5b7c50a3 100644 --- a/public/language/uk/admin/dashboard.json +++ b/public/language/uk/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "Теми", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "Останні 7 Днів", "page-views-thirty": "Останні 30 Днів", "page-views-last-day": "Останні 24 Години", - "page-views-custom": "Заданий Період", + "page-views-custom": "Custom Range", "page-views-custom-start": "Початок Періоду", "page-views-custom-end": "Кінець Періоду", "page-views-custom-help": "Вкажіть календарний період, за який ви хочете побачити переглянуті сторінки. Якщо ви не можете використати селектор дат, допустимий формат дати YYYY-MM-DD", diff --git a/public/language/uk/admin/manage/users.json b/public/language/uk/admin/manage/users.json index 8ed24dc793..4aef688b48 100644 --- a/public/language/uk/admin/manage/users.json +++ b/public/language/uk/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 per page", "500-per-page": "500 per page", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "За ID користувача", "search.uid-placeholder": "Введіть ID користувача для пошуку", "search.username": "За іменем", diff --git a/public/language/uk/admin/menu.json b/public/language/uk/admin/menu.json index d649a6e9ab..aa11bef944 100644 --- a/public/language/uk/admin/menu.json +++ b/public/language/uk/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "Логи", "advanced/errors": "Помилки", "advanced/cache": "Кеш", + "advanced/jobs": "Jobs", "development/logger": "Логування", "development/info": "Інформація", diff --git a/public/language/uk/admin/settings/activitypub.json b/public/language/uk/admin/settings/activitypub.json index 0486870db1..64508849aa 100644 --- a/public/language/uk/admin/settings/activitypub.json +++ b/public/language/uk/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/uk/admin/settings/general.json b/public/language/uk/admin/settings/general.json index 96962dfe01..76f2cfabe9 100644 --- a/public/language/uk/admin/settings/general.json +++ b/public/language/uk/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "Ключові слова сайту", "keywords-placeholder": "Ключові слова, що описують вашу спільноту, розділені комами", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "Зображення", "logo.image-placeholder": "Шлях до логотипу для відображення в шапці форуму", "logo.upload": "Завантажити", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "Зовнішні посилання", "outgoing-links.warning-page": "Використовувати сторінку попередження про зовнішній перехід", "search": "Search", diff --git a/public/language/uk/error.json b/public/language/uk/error.json index 7f12ac168d..81b65bd963 100644 --- a/public/language/uk/error.json +++ b/public/language/uk/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Невірні дані", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "Некоректний формат JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/uk/world.json b/public/language/uk/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/uk/world.json +++ b/public/language/uk/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/ur/admin/advanced/jobs.json b/public/language/ur/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/ur/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/ur/admin/dashboard.json b/public/language/ur/admin/dashboard.json index 7513fa354d..8384882381 100644 --- a/public/language/ur/admin/dashboard.json +++ b/public/language/ur/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "موضوعات", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "آخری 7 دن", "page-views-thirty": "آخری 30 دن", "page-views-last-day": "آخری 24 گھنٹے", - "page-views-custom": "مرضی کا وقفہ", + "page-views-custom": "Custom Range", "page-views-custom-start": "شروع کی تاریخ", "page-views-custom-end": "ختم کی تاریخ", "page-views-custom-help": "صفحہ مناظر دیکھنے کے لیے تاریخوں کا وقفہ درج کریں۔ اگر کیلنڈر انتخاب کے لیے ظاہر نہ ہو، تو آپ تاریخوں کو فارمیٹ YYYY-MM-DD میں درج کر سکتے ہیں۔", diff --git a/public/language/ur/admin/manage/users.json b/public/language/ur/admin/manage/users.json index ffc2f52575..7f7565827d 100644 --- a/public/language/ur/admin/manage/users.json +++ b/public/language/ur/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "250 فی صفحہ", "500-per-page": "500 فی صفحہ", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "صارف شناخت کنندہ کے ذریعے", "search.uid-placeholder": "تلاش کرنے کے لیے صارف شناخت کنندہ درج کریں", "search.username": "صارف نام کے ذریعے", diff --git a/public/language/ur/admin/menu.json b/public/language/ur/admin/menu.json index da4accb456..bb05f433f3 100644 --- a/public/language/ur/admin/menu.json +++ b/public/language/ur/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "لاگس", "advanced/errors": "غلطیاں", "advanced/cache": "کیش", + "advanced/jobs": "Jobs", "development/logger": "لاگ", "development/info": "معلومات", diff --git a/public/language/ur/admin/settings/activitypub.json b/public/language/ur/admin/settings/activitypub.json index 34869aa058..fea9adb3a6 100644 --- a/public/language/ur/admin/settings/activitypub.json +++ b/public/language/ur/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/ur/admin/settings/general.json b/public/language/ur/admin/settings/general.json index 51e14ab67f..b2594add22 100644 --- a/public/language/ur/admin/settings/general.json +++ b/public/language/ur/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "ویب سائٹ کی تفصیل", "keywords": "ویب سائٹ کے کلیدی الفاظ", "keywords-placeholder": "آپ کی کمیونٹی کی وضاحت کرنے والے کلیدی الفاظ، کوموں سے الگ کیے گئے۔", - "logo-and-icons": "ویب سائٹ کا لوگو اور آئیکنز", + "logo-and-icons": "Media & Branding", "logo.image": "تصویر", "logo.image-placeholder": "فورم کے ہیڈر میں دکھائے جانے والے لوگو کا پاتھ", "logo.upload": "اپ لوڈ", @@ -35,6 +35,8 @@ "touch-icon.help": "تجویز کردہ سائز اور فارمیٹ: 512x512، صرف PNG فارمیٹ میں۔ اگر ٹچ آئیکن بیان نہیں کیا گیا تو NodeBB ویب سائٹ کے فیویکن کا استعمال کرے گا۔", "maskable-icon": "ماسک ایبل آئیکن (ہوم اسکرین کے لیے)", "maskable-icon.help": "تجویز کردہ سائز اور فارمیٹ: 512x512، صرف PNG فارمیٹ میں۔ اگر ماسک ایبل آئیکن بیان نہیں کیا گیا تو NodeBB ٹچ آئیکن کا استعمال کرے گا۔", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "باہر جانے والے لنکس", "outgoing-links.warning-page": "باہری لنکس پر کلک کرنے پر تنبیہی صفحہ دکھائیں", "search": "تلاش", diff --git a/public/language/ur/error.json b/public/language/ur/error.json index 58704ad9d3..5c61957dff 100644 --- a/public/language/ur/error.json +++ b/public/language/ur/error.json @@ -1,5 +1,6 @@ { "invalid-data": "غلط ڈیٹا", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "غلط JSON", "wrong-parameter-type": "پراپرٹی '%1' کے لیے %3 قسم کی قدر متوقع تھی، لیکن اس کے بجائے %2 موصول ہوا", "required-parameters-missing": "اس API کال سے ضروری پیرامیٹرز غائب ہیں: %1", diff --git a/public/language/ur/world.json b/public/language/ur/world.json index 056371c5ff..62b8f7d916 100644 --- a/public/language/ur/world.json +++ b/public/language/ur/world.json @@ -1,6 +1,8 @@ { "name": "جهان", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "اسی طرح، اگر اس فورم سے باہر کے صارفین آپ کو فالو کرنا شروع کر دیں، تو آپ کی پوسٹس ان کے ایپلیکیشنز اور ویب سائٹس پر ظاہر ہونا شروع ہو جائیں گی۔", "help.next-generation": "یہ سوشل نیٹ ورک کی نئی نسل ہے۔ آج ہی سے حصہ ڈالنا شروع کریں!", - "onboard.title": "فیڈی ورس کی طرف آپ کی کھڑکی…", - "onboard.what": "یہ آپ کی ذاتی نوعیت کی کیٹیگری ہے جو صرف اس فورم سے باہر کے مواد پر مشتمل ہے۔ یہاں وہ چیزیں ظاہر ہوتی ہیں جو آپ کے فالو کیے ہوئے لوگوں نے بنائیں یا شیئر کیں۔", - "onboard.why": "اس فورم سے باہر بہت کچھ ہو رہا ہے، اور ہر چیز آپ کے مفادات سے مطابقت نہیں رکھتی۔ اس لیے مخصوص لوگوں کو فالو کرنا یہ ظاہر کرنے کا بہترین طریقہ ہے کہ آپ ان سے مزید دیکھنا چاہتے ہیں۔", - "onboard.how": "اس دوران، آپ اس فورم کے قابل رسائی مواد کو دیکھنے کے لیے اوپر کے بٹن استعمال کر سکتے ہیں۔ اس طرح آپ نئے مواد کی دریافت شروع کر سکتے ہیں!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/language/vi/admin/advanced/jobs.json b/public/language/vi/admin/advanced/jobs.json new file mode 100644 index 0000000000..7cd625a139 --- /dev/null +++ b/public/language/vi/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Công việc", + "job-name": "Tên Công Việc", + "schedule": "Lên lịch", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/vi/admin/dashboard.json b/public/language/vi/admin/dashboard.json index a68923b6ae..4ab97b7dcf 100644 --- a/public/language/vi/admin/dashboard.json +++ b/public/language/vi/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "Người Mới", "posts": "Lượt Đăng", "topics": "Chủ đề", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "Bài Đăng Từ Xa", + "remote-topics": "Chủ Đề Từ Xa", + "messages": "Tin nhắn", "page-views-seven": "7 ngày trước", "page-views-thirty": "30 ngày trước", "page-views-last-day": "24 giờ trước", - "page-views-custom": "Tùy Chỉnh Phạm Vi Ngày", + "page-views-custom": "Phạm Vi Tùy Chỉnh", "page-views-custom-start": "Phạm vi bắt đầu", "page-views-custom-end": "Phạm vi kết thúc", "page-views-custom-help": "Nhập phạm vi ngày mà bạn muốn xem lượt xem trang. Nếu không có bộ chọn ngày, chấp nhận định dạng là YYYY-MM-DD", diff --git a/public/language/vi/admin/manage/categories.json b/public/language/vi/admin/manage/categories.json index 1e265b3bdf..9823d362d3 100644 --- a/public/language/vi/admin/manage/categories.json +++ b/public/language/vi/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "Chọn Chuyên Mục", "set-parent-category": "Đặt Chuyên Mục Chính", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "Bạn có thể cấu hình quyền truy cập cho từng phần của trang web trong phần này. Quyền hạn có thể được cấp cho từng người dùng hoặc từng nhóm.", "privileges.category-selector": "Cấu hình đặc quyền cho", "privileges.warning": "Ghi chú: Cài đặt đặc quyền có hiệu lực lập tức. Không cần phải lưu danh mục sau khi điều chỉnh cài đặt này.", "privileges.section-viewing": "Đặc Quyền Xem", diff --git a/public/language/vi/admin/manage/custom-reasons.json b/public/language/vi/admin/manage/custom-reasons.json index 90a2e620af..dee021f1da 100644 --- a/public/language/vi/admin/manage/custom-reasons.json +++ b/public/language/vi/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "title": "Quản Lý Lý Do Tùy Chỉnh", + "create-reason": "Tạo Lý Do", + "edit-reason": "Sửa Lý Do", + "reasons-help": "Lý do là những lời giải thích được định sẵn, được sử dụng khi cấm hoặc tắt tiếng người dùng, hoặc khi từ chối bài đăng trong hàng đợi bài đăng.", + "reason-title": "Tiêu đề", + "reason-type": "Loại", + "reason-body": "Thân", + "reason-all": "Tất cả", + "reason-ban": "Cấm", + "reason-mute": "Im lặng", + "reason-post-queue": "Xếp Hàng Bài Đăng", + "reason-type-help": "Loại hành động mà lý do này áp dụng. Nếu chọn 'Tất cả', lý do này sẽ áp dụng cho tất cả các loại hành động.", + "custom-reasons-saved": "Lý do tùy chỉnh đã được lưu thành công.", + "delete-reason-confirm-x": "Bạn có chắc chắn muốn xóa lý do tùy chỉnh với tiêu đề %1?" } \ No newline at end of file diff --git a/public/language/vi/admin/manage/privileges.json b/public/language/vi/admin/manage/privileges.json index 6b56cdc2d5..7183f47ff4 100644 --- a/public/language/vi/admin/manage/privileges.json +++ b/public/language/vi/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "Truy Cập Chủ Đề", "create-topics": "Tạo Chủ Đề", "reply-to-topics": "Trả Lời Chủ Đề", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "Chủ Đề Đăng Chéo", "schedule-topics": "Lên Lịch Chủ Đề", "tag-topics": "Gắn Thẻ Chủ Đề", "edit-posts": "Chỉnh Sửa Bài Đăng", diff --git a/public/language/vi/admin/manage/uploads.json b/public/language/vi/admin/manage/uploads.json index 32f4d447e3..39e2308e7c 100644 --- a/public/language/vi/admin/manage/uploads.json +++ b/public/language/vi/admin/manage/uploads.json @@ -2,7 +2,7 @@ "manage-uploads": "Quản Lý Tải Lên", "upload-file": "Tải Lên Tệp", "filename": "Tên Tệp", - "usage": "Dùng Bài Đăng", + "usage": "Bài Đăng Sử Dụng", "orphaned": "Đơn độc", "size/filecount": "Kích cỡ/ Số tệp", "confirm-delete": "Bạn có chắc muốn xóa tệp này không?", diff --git a/public/language/vi/admin/manage/users.json b/public/language/vi/admin/manage/users.json index 2c76cfb9f0..349d33d288 100644 --- a/public/language/vi/admin/manage/users.json +++ b/public/language/vi/admin/manage/users.json @@ -23,7 +23,7 @@ "purge": "Xóa Người DùngNội Dung", "download-csv": "Tải về CSV", "custom-user-fields": "Trường Người Dùng Tùy Chỉnh", - "custom-reasons": "Custom Reasons", + "custom-reasons": "Lý Do Tùy Chỉnh", "manage-groups": "Quản Lý Nhóm", "set-reputation": "Đặt Uy Tín", "add-group": "Thêm Nhóm", @@ -40,6 +40,7 @@ "250-per-page": "250 mỗi trang", "500-per-page": "500 mỗi trang", + "search.help": "Dùng "*" thực hiện tìm kiếm một phần, ví dụ "*query"", "search.uid": "Bởi ID Người Dùng", "search.uid-placeholder": "Nhập ID người dùng để tìm", "search.username": "Theo Tên Người Dùng", @@ -55,7 +56,7 @@ "inactive.12-months": "12 tháng", "users.uid": "uid", - "users.user-id": "User ID", + "users.user-id": "ID Người Dùng", "users.username": "tên đăng nhập", "users.email": "thư điện tử", "users.no-email": "(không có email)", @@ -64,7 +65,7 @@ "users.validation-pending": "Đang Chờ Xác Thực", "users.validation-expired": "Đã Hết Hạn Xác Thực", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "IPs Gần Đây", "users.postcount": "số bài", "users.reputation": "uy tín", "users.flags": "gắn cờ", @@ -80,11 +81,11 @@ "temp-ban.length": "Dài", "temp-ban.reason": "Lý do (Không bắt buộc)", - "temp-ban.select-reason": "Select a reason", + "temp-ban.select-reason": "Chọn lý do", "temp-ban.hours": "Giờ", "temp-ban.days": "Ngày", "temp-ban.explanation": "Nhập khoảng thời gian cho lệnh cấm. Lưu ý rằng thời gian bằng 0 sẽ là một lệnh cấm vĩnh viễn.", - "temp-mute.explanation": "Enter the length of time for the mute. Note that a time of 0 will be a considered a permanent mute.", + "temp-mute.explanation": "Nhập khoảng thời gian tắt tiếng. Lưu ý rằng thời gian 0 sẽ được coi là tắt tiếng vĩnh viễn.", "alerts.confirm-ban": "Bạn có chắc muốn cấm người dùng này mãi mãi?", "alerts.confirm-ban-multi": "Bạn có chắc muốn cấm những người dùng này mãi mãi?", diff --git a/public/language/vi/admin/menu.json b/public/language/vi/admin/menu.json index f42d3edcd4..bf999805fb 100644 --- a/public/language/vi/admin/menu.json +++ b/public/language/vi/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "Cài đặt %1", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "Liên đoàn", + "federation/general": "Chung", + "federation/content": "Nội dung", + "federation/rules": "Phân loại", + "federation/relays": "Chuyển tiếp", + "federation/pruning": "Lưu trữ", + "federation/safety": "Tin cậy & An toàn", "section-appearance": "Trực quan", "appearance/themes": "Giao diện", @@ -78,6 +78,7 @@ "advanced/logs": "Nhật ký", "advanced/errors": "Lỗi", "advanced/cache": "Bộ nhớ đệm", + "advanced/jobs": "Công việc", "development/logger": "Ghi nhật ký", "development/info": "Thông tin", diff --git a/public/language/vi/admin/settings/activitypub.json b/public/language/vi/admin/settings/activitypub.json index 0f36ae3b8c..e1f3cd8804 100644 --- a/public/language/vi/admin/settings/activitypub.json +++ b/public/language/vi/admin/settings/activitypub.json @@ -42,13 +42,14 @@ "server-filtering": "Lọc", "count": "NodeBB này hiện đã biết về %1 máy chủ", - "server.filter-help": "Chỉ định các máy chủ mà bạn muốn cấm liên kết với NodeBB của mình. Ngoài ra, bạn có thể chọn tham gia có chọn lọc cho phép liên kết có chọn lọc với các máy chủ cụ thể. Cả hai tùy chọn đều được hỗ trợ, mặc dù chúng loại trừ lẫn nhau.", + "server.filter-help": "Chỉ ra các máy chủ mà bạn muốn cấm liên kết với NodeBB của mình. Ngoài ra, bạn có thể chọn tham gia có chọn lọc cho phép liên kết có chọn lọc với các máy chủ cụ thể. Cả hai tùy chọn đều được hỗ trợ, mặc dù chúng loại trừ lẫn nhau.", "server.filter-help-hostname": "Chỉ nhập tên máy chủ bên dưới (vd: example.org), tách nhau bằng ngắt dòng.", "server.filter-allow-list": "Dùng nó làm Danh Sách Cho Phép Thay Thế", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "Ra ngoài", + "content.summary-limit": "Số lượng ký tự sau đó bản tóm tắt sẽ được tạo.", + "content.summary-limit-help": "Khi nội dung được phân phối vượt quá số lượng ký tự này, tóm tắt được tạo ra, bao gồm tất cả các câu hoàn chỉnh trước giới hạn này. (Mặc định: 500)", + "content.break-string": "Dấu phân cách Ghi chú/Bài đăng", + "content.break-string-help": "Dấu phân cách này có thể được người dùng thành thạo chèn thủ công khi soạn thảo chủ đề mới. Nó hướng dẫn NodeBB sử dụng nội dung cho đến thời điểm đó như một phần của tóm tắt. Nếu chuỗi này không được sử dụng, thì phương án dự phòng dựa trên số lượng ký tự sẽ được áp dụng. (Mặc định: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/vi/admin/settings/advanced.json b/public/language/vi/admin/settings/advanced.json index b6c2785458..9b0446f571 100644 --- a/public/language/vi/admin/settings/advanced.json +++ b/public/language/vi/admin/settings/advanced.json @@ -33,7 +33,7 @@ "traffic.enable": "Bật Quản Lý Lưu Lượng", "traffic.event-lag": "Ngưỡng Trễ Vòng Lặp Sự Kiện (mili-giây)", "traffic.event-lag-help": "Giảm giá trị này sẽ giảm thời gian chờ tải trang, nhưng cũng sẽ hiển thị thông báo \"tải quá mức\" cho nhiều người dùng hơn. (Yêu cầu khởi động lại)", - "traffic.lag-check-interval": "Khoảng thời gian kiểm tra (mili giây)", + "traffic.lag-check-interval": "Chu kỳ kiểm tra (mili giây)", "traffic.lag-check-interval-help": "Việc hạ thấp giá trị này khiến NodeBB trở nên nhạy cảm hơn với tải đột biến, nhưng cũng có thể khiến kiểm tra trở nên quá nhạy. (Yêu cầu khởi động lại)", "sockets.settings": "Cài Đặt WebSocket", diff --git a/public/language/vi/admin/settings/email.json b/public/language/vi/admin/settings/email.json index 5ea7eec8aa..7fac296238 100644 --- a/public/language/vi/admin/settings/email.json +++ b/public/language/vi/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "Việc gộp các kết nối ngăn NodeBB tạo kết nối mới cho mọi email. Tùy chọn này chỉ áp dụng nếu Truyền tải SMTP được bật.", "smtp-transport.allow-self-signed": "Cho phép chứng chỉ tự ký", "smtp-transport.allow-self-signed-help": "Kích hoạt cài đặt này sẽ cho phép bạn sử dụng các chứng chỉ TLS tự ký hoặc không hợp lệ.", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "Email kiểm thử SMTP đã được gửi thành công.", "template": "Sửa Mẫu Email", "template.select": "Chọn Mẫu Email", "template.revert": "Hoàn Nguyên về Bản Gốc", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "Kiểm tra cài đặt SMTP", "testing": "Email Kiểm Tra", - "testing.success": "Test Email Sent.", + "testing.success": "Đã Gửi Email Kiểm Thử.", "testing.select": "Chọn Mẫu Email", "testing.send": "Gửi Email Kiểm Tra", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" sẽ được dùng để gửi email thử nghiệm.", + "testing.send-help-smtp": "Giao thức SMTP đã được kích hoạt và sẽ được sử dụng để gửi email.", + "testing.send-help-no-plugin": "Hiện chưa có plugin gửi email nào được cài đặt, nodemailer sẽ được sử dụng theo mặc định.", + "testing.send-help": "Email thử nghiệm sẽ được gửi đến địa chỉ email của người dùng hiện đang đăng nhập, sử dụng các cài đặt đã lưu trên trang này.", "subscriptions": "Email Bản Tóm Tắt", "subscriptions.disable": "Tắt email bản tóm tắt", "subscriptions.hour": "Giờ Tóm Tắt", diff --git a/public/language/vi/admin/settings/general.json b/public/language/vi/admin/settings/general.json index a45f6a551f..bfbdbde36a 100644 --- a/public/language/vi/admin/settings/general.json +++ b/public/language/vi/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Mô Tả Trang", "keywords": "Từ Khóa Trang", "keywords-placeholder": "Các từ khóa mô tả cộng đồng của bạn, được phân tách bằng dấu phẩy", - "logo-and-icons": "Lô-gô & Biểu Tượng Trang", + "logo-and-icons": "Media & Branding", "logo.image": "Ảnh", "logo.image-placeholder": "Đường dẫn đến biểu trưng để hiển thị phần đầu diễn đàn", "logo.upload": "Tải lên", @@ -35,6 +35,8 @@ "touch-icon.help": "Kích cỡ và định dạng được đề xuất: 512x512, chỉ định dạng PNG. Nếu không có biểu tượng cảm ứng nào, NodeBB sẽ quay trở lại sử dụng favicon.", "maskable-icon": "Biểu tượng có thể che được (Màn Hình Trang Chủ)", "maskable-icon.help": "Kích thước và định dạng nên là: 512x512, chỉ định dạng PNG. Nếu không có biểu tượng có thể che được nào được chỉ định, NodeBB sẽ trở lại Biểu Tượng Chạm.", + "screenshot": "Ảnh chụp màn hình", + "screenshot.help": "Kích thước và định dạng được đề xuất: từ 320px đến 3480px, chỉ định dạng JPG và PNG. Nếu không chỉ định ảnh chụp màn hình, NodeBB sẽ sử dụng ảnh chụp màn hình mặc định.", "outgoing-links": "Liên Kết Đi", "outgoing-links.warning-page": "Sử Dụng Trang Cảnh Báo Liên Kết Đi", "search": "Tìm kiếm", diff --git a/public/language/vi/admin/settings/notifications.json b/public/language/vi/admin/settings/notifications.json index 4a556625c7..c28d44f5f3 100644 --- a/public/language/vi/admin/settings/notifications.json +++ b/public/language/vi/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "Liên Kết Thông Báo Chào Mừng", "welcome-notification-uid": "Thông Báo Chào Mừng Người Dùng (UID)", "post-queue-notification-uid": "Người Dùng Đợi Đăng (UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "Thời gian trễ khi gửi email thông báo (giây)", + "notification-delay-help": "Nếu người dùng đã đọc thông báo trong khoảng thời gian này, email sẽ không được gửi.
Mặc định: 60 giây." } \ No newline at end of file diff --git a/public/language/vi/admin/settings/post.json b/public/language/vi/admin/settings/post.json index adf16f815d..7079af5639 100644 --- a/public/language/vi/admin/settings/post.json +++ b/public/language/vi/admin/settings/post.json @@ -32,7 +32,7 @@ "timestamp.cut-off-help": "Ngày & giờ sẽ được hiển thị tương đối (VD: \"3 giờ trước\" / \"5 ngày trước\"), và địa phương hóa thành nhiều\n\t\t\t\t\tngôn ngữ. Sau một thời gian, dòng chữ này có thể tự chuyển sang hiển thị ngày giờ địa phương\n\t\t\t\t\t(VD: 5 Tháng 11, 2016 15:30).
(Mặc định: 30, hoặc một tháng). Đặt là 0 để luôn hiển thị ngày tháng, để trống để luôn hiển thị thời gian tương đối.", "timestamp.necro-threshold": "Ngưỡng Necro (ngày)", "timestamp.necro-threshold-help": "Một thông báo sẽ được hiển thị giữa các bài đăng nếu thời gian giữa chúng dài hơn ngưỡng yêu cầu. (Mặc định: 7, hoặc một tuần). Đặt thành 0 để tắt.", - "timestamp.topic-views-interval": "Khoảng thời gian xem chủ đề tăng dần (phút)", + "timestamp.topic-views-interval": "Chu kỳ lượt xem chủ đề tăng dần (phút)", "timestamp.topic-views-interval-help": "Lượt xem chủ đề sẽ tăng lên một lần sau mỗi X phút được đặt bởi cài đặt này.", "teaser": "Đoạn Giới Thiệu Bài Viết", "teaser.last-post": "Gần đây – Hiển thị bài đăng mới nhất, bao gồm cả bài gốc, nếu không có câu trả lời", diff --git a/public/language/vi/admin/settings/uploads.json b/public/language/vi/admin/settings/uploads.json index 68e044096f..2c004dadaf 100644 --- a/public/language/vi/admin/settings/uploads.json +++ b/public/language/vi/admin/settings/uploads.json @@ -21,8 +21,8 @@ "reject-image-width-help": "Hình ảnh rộng hơn giá trị này sẽ bị từ chối.", "reject-image-height": "Chiều Cao Ảnh Tối Đa (pixel)", "reject-image-height-help": "Hình ảnh cao hơn giá trị này sẽ bị từ chối.", - "convert-pasted-images-to": "Convert pasted images to:", - "convert-pasted-images-to-default": "No Conversion (Keep Original Format)", + "convert-pasted-images-to": "Chuyển đổi hình ảnh đã dán thành:", + "convert-pasted-images-to-default": "Không Chuyển Đổi (Giữ Định Dạng Gốc)", "convert-pasted-images-to-png": "PNG", "convert-pasted-images-to-jpeg": "JPEG", "convert-pasted-images-to-webp": "WebP", @@ -40,7 +40,7 @@ "default-avatar": "Ảnh Đại Diện Mặc Định", "upload": "Tải lên", "profile-image-dimension": "Kích Thước Ảnh Hồ Sơ", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(theo pixel, mặc định: 200 pixel)", "max-profile-image-size": "Kích Cỡ Tệp Ảnh Hồ Sơ Tối Đa", "max-profile-image-size-help": "(tính bằng kibibyte, mặc định: 256 KiB)", "max-cover-image-size": "Kích Cỡ Tệp Ảnh Bìa Tối Đa", diff --git a/public/language/vi/aria.json b/public/language/vi/aria.json index b82f396907..71fa3f06de 100644 --- a/public/language/vi/aria.json +++ b/public/language/vi/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "Thẻ người dùng đã xem", "delete-upload-button": "Xóa nút tải lên", "group-page-link-for": "Liên kết trang nhóm cho %1", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "Hiển thị Bài Đăng Chéo" } \ No newline at end of file diff --git a/public/language/vi/category.json b/public/language/vi/category.json index eb43072ed6..6b190f0501 100644 --- a/public/language/vi/category.json +++ b/public/language/vi/category.json @@ -1,8 +1,8 @@ { "category": "Danh mục", "subcategories": "Danh mục phụ", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "Thế giới", + "uncategorized.description": "Các chủ đề từ bên ngoài diễn đàn này. Quan điểm và ý kiến ​​được trình bày ở đây có thể không phản ánh quan điểm của diễn đàn này và các thành viên của nó.", "handle.description": "Có thể theo dõi danh mục này từ mạng xã hội mở thông qua xử lý %1", "new-topic-button": "Chủ Đề Mới", "guest-login-post": "Đăng nhập để đăng bài", diff --git a/public/language/vi/error.json b/public/language/vi/error.json index 3a6155a0ba..76ab019087 100644 --- a/public/language/vi/error.json +++ b/public/language/vi/error.json @@ -1,5 +1,6 @@ { "invalid-data": "Dữ Liệu Không Hợp Lệ", + "invalid-config-field-value": "Giá trị không hợp lệ cho trường cấu hình \"%1\": %2", "invalid-json": "JSON không hợp lệ", "wrong-parameter-type": "Giá trị của loại %3 được mong đợi cho thuộc tính `%1`, nhưng thay vào đó, %2 đã được nhận", "required-parameters-missing": "Các thông số bắt buộc bị thiếu trong lệnh gọi API này: %1", @@ -32,7 +33,7 @@ "invalid-path": "Đường dẫn không hợp lệ", "folder-exists": "Thư mục tồn tại", "invalid-pagination-value": "Giá trị phân trang không hợp lệ, tối thiểu là %1 và tối đa là %2", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "Giá trị cắt không hợp lệ, chưa đọc, phải ít nhất là 1 và nhiều nhất là %1.", "username-taken": "Tên đăng nhập có rồi", "email-taken": "Địa chỉ email đã được sử dụng.", "email-nochange": "Email đã nhập giống với email đã có trong tệp.", @@ -148,7 +149,7 @@ "post-already-restored": "Bài viết này đã được khôi phục", "topic-already-deleted": "Chủ đề này đã bị xóa", "topic-already-restored": "Chủ đề này đã được khôi phục", - "topic-already-crossposted": "This topic has already been cross-posted there.", + "topic-already-crossposted": "Chủ đề này đã được đăng tải chéo ở đó rồi.", "cant-purge-main-post": "Bạn không thể xoá bài viết chính, thay vào đó vui lòng xóa chủ đề", "topic-thumbnails-are-disabled": "Ảnh Thumbnails chủ đề đã bị tắt", "invalid-file": "Tệp Không Hợp Lệ", @@ -227,10 +228,10 @@ "invalid-session-text": "Có vẻ như phiên đăng nhập của bạn không còn hoạt động. Vui lòng làm mới trang này.", "session-mismatch": "‎Phiên Không Khớp‎", "session-mismatch-text": "Có vẻ như phiên đăng nhập của bạn không còn khớp với máy chủ. Vui lòng làm mới trang này.", - "no-topics-selected": "Không chọn chủ đề!", + "no-topics-selected": "Chưa chọn chủ đề!", "cant-move-to-same-topic": "Bạn không thể đưa bài đăng vào cùng chủ đề!", "cant-move-topic-to-same-category": "Không thể di chuyển chủ đề đến cùng danh mục!", - "cant-move-topic-to-from-remote-categories": "You cannot move topics in or out of remote categories; consider cross-posting instead.", + "cant-move-topic-to-from-remote-categories": "Bạn không thể di chuyển chủ đề vào hoặc ra khỏi các danh mục từ xa; hãy cân nhắc đăng chéo bài viết thay thế.", "cannot-block-self": "Bạn không thể tự khóa bạn!", "cannot-block-privileged": "Bạn không thể khóa quản trị viên hay người kiểm duyệt chung.", "cannot-block-guest": "Khách không thể chặn người dùng khác", @@ -253,7 +254,7 @@ "api.401": "Một phiên đăng nhập hợp lệ không được tìm thấy. Hãy đăng nhập và thử lại.", "api.403": "Bạn không được phép thực hiện lệnh gọi này", "api.404": "Lệnh gọi API không hợp lệ", - "api.413": "The request payload is too large", + "api.413": "Kích thước dữ liệu yêu cầu quá lớn.", "api.426": "HTTPS là bắt buộc đối với các yêu cầu đối với api viết, vui lòng gửi lại yêu cầu của bạn qua HTTPS", "api.429": "Bạn đã đưa ra quá nhiều yêu cầu, vui lòng thử lại sau", "api.500": "Đã xảy ra lỗi không mong muốn khi cố gắng thực hiện yêu cầu của bạn.", diff --git a/public/language/vi/global.json b/public/language/vi/global.json index 6af6cf9460..f9cc9bcada 100644 --- a/public/language/vi/global.json +++ b/public/language/vi/global.json @@ -49,7 +49,7 @@ "header.account": "Tài khoản", "header.navigation": "Điều hướng", "header.manage": "Quản lý", - "header.drafts": "Bản thảo", + "header.drafts": "Bản nháp", "header.world": "Thế giới", "notifications.loading": "Đang Tải Thông Báo", "chats.loading": "Đang Tải Trò Chuyện", @@ -68,7 +68,7 @@ "users": "Người dùng", "topics": "Chủ Đề", "posts": "Bài Viết", - "crossposts": "Cross-posts", + "crossposts": "Đăng chéo", "x-posts": "%1 bài đăng", "x-topics": "%1 chủ để", "x-reputation": "%1 uy tín", @@ -137,7 +137,7 @@ "allowed-file-types": "Loại cho phép là %1", "unsaved-changes": "Bạn có những thay đổi chưa lưu. Bạn có chắc muốn điều hướng đi?", "reconnecting-message": "Có vẻ như bạn đã mất kết nối tới %1, hãy đợi trong khi chúng tôi cố gắng kết nối lại.", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "Đã kết nối lại với %1 thành công.", "play": "Phát", "cookies.message": "Trang web này sử dụng cookie để đảm bảo bạn có được trải nghiệm tốt.", "cookies.accept": "Hiểu rồi!", diff --git a/public/language/vi/groups.json b/public/language/vi/groups.json index e8c0da765c..1231b88ed4 100644 --- a/public/language/vi/groups.json +++ b/public/language/vi/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "Nhóm", "all-groups": "Tất cả các nhóm", "groups": "Nhóm", "members": "Thành Viên", - "x-members": "%1 member(s)", + "x-members": "%1 thành viên", "view-group": "Xem Nhóm", "owner": "Người Sở Hữu Nhóm", "new-group": "Tạo Nhóm Mới", diff --git a/public/language/vi/modules.json b/public/language/vi/modules.json index 6834051f81..912ef6c505 100644 --- a/public/language/vi/modules.json +++ b/public/language/vi/modules.json @@ -113,8 +113,8 @@ "composer.cancel-scheduling": "Hủy Lịch Trình", "composer.change-schedule-date": "Đổi Ngày", "composer.set-schedule-date": "Đặt Ngày", - "composer.discard-all-drafts": "Hủy tất cả bản nháp", - "composer.no-drafts": "Bạn không có bản nháp nào", + "composer.discard-all-drafts": "Loại bỏ tất cả bản nháp", + "composer.no-drafts": "Bạn không có bản nháp", "composer.discard-draft-confirm": "Bạn có muốn hủy bản nháp này không?", "composer.remote-pid-editing": "Sửa bài đăng từ xa", "composer.remote-pid-content-immutable": "Nội dung của bài viết từ xa không thể được chỉnh sửa. Tuy nhiên, bạn có thể thay đổi tiêu đề và gắn thẻ chủ đề.", diff --git a/public/language/vi/notifications.json b/public/language/vi/notifications.json index c62ae430b1..6dadfd1d73 100644 --- a/public/language/vi/notifications.json +++ b/public/language/vi/notifications.json @@ -30,8 +30,8 @@ "new-messages-in": "%1 tin nhắn mới trong %2", "user-posted-in-public-room": "%1 đã viết trong %3", "user-posted-in-public-room-dual": "%1%2 đã viết trong %4", - "user-posted-in-public-room-triple": "%1, %2 and %3 wrote in %5", - "user-posted-in-public-room-multiple": "%1, %2 and %3 others wrote in %5", + "user-posted-in-public-room-triple": "%1, %2%3 đã viết trong %5", + "user-posted-in-public-room-multiple": "%1, %2 và %3 người khác đã viết trong %5", "upvoted-your-post-in": "%1 đã ủng hộ bài của bạn trong %2", "upvoted-your-post-in-dual": "%1%2 đã ủng hộ bài của bạn trong %3", "upvoted-your-post-in-triple": "%1, %2%3 đã ủng hộ bài của bạn trong %4", @@ -55,7 +55,7 @@ "user-posted-topic-with-tag": "%1 đã đăng %2 (đã gắn thẻ %3)", "user-posted-topic-with-tag-dual": "%1 đã đăng %2 (đã gắn thẻ %3 và %4)", "user-posted-topic-with-tag-triple": "%1 đã đăng %2 (đã gắn thẻ %3, %4, và %5)", - "user-posted-topic-with-tag-multiple": "%1 posted %2 (tagged %3)", + "user-posted-topic-with-tag-multiple": "%1 đã đăng %2 (đã gắn thẻ %3)", "user-posted-topic-in-category": "%1 đã viết %2 trong %3", "user-started-following-you": "%1 bắt đầu theo dõi bạn.", "user-started-following-you-dual": "%1%2 bắt đầu theo dõi bạn.", @@ -65,7 +65,7 @@ "new-register-multiple": "Có %1 yêu cầu đăng ký đang chờ đánh giá.", "flag-assigned-to-you": "Cờ %1 đã được giao cho bạn", "post-awaiting-review": "Bài đăng chờ đánh giá", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "Chủ đề đang chờ xem xét", "profile-exported": "%1 đã xuất hồ sơ, bấm để tải xuống", "posts-exported": "%1 đã xuất bài viết, nhấn tải xuống", "uploads-exported": "%1 đã xuất tải lên, nhấn tải xuống", diff --git a/public/language/vi/reset_password.json b/public/language/vi/reset_password.json index a8cfb41fc3..261cec9f0d 100644 --- a/public/language/vi/reset_password.json +++ b/public/language/vi/reset_password.json @@ -12,7 +12,7 @@ "enter-email-address": "Nhập địa chỉ Email", "password-reset-sent": "Nếu có địa chỉ cụ thể ứng với tài khoản người dùng hiện có, một email đặt lại mật khẩu đã được gửi. Xin lưu ý chỉ có một email được gửi mỗi phút.", "invalid-email": "Email không đúng/không tồn tại!", - "password-too-short": "Mật khẩu bạn nhập quá ngắn, vui lòng chọn một mật khẩu khác.", + "password-too-short": "Mật khẩu đã nhập quá ngắn, vui lòng chọn một mật khẩu khác.", "passwords-do-not-match": "Hai mật khẩu bạn nhập không khớp với nhau.", "password-expired": "Mật khẩu của bạn đã hết hạn, vui lòng chọn một mật khẩu mới." } \ No newline at end of file diff --git a/public/language/vi/search.json b/public/language/vi/search.json index 43b468535f..a71c3441bb 100644 --- a/public/language/vi/search.json +++ b/public/language/vi/search.json @@ -103,8 +103,8 @@ "search-preferences-saved": "Đã lưu tùy chọn tìm kiếm", "search-preferences-cleared": "Đã xóa tùy chọn tìm kiếm", "show-results-as": "Hiện thị kết quả theo", - "show-results-as-topics": "Hiển thị kết quả dưới dạng chủ đề", - "show-results-as-posts": "Hiển thị kết quả dưới dạng bài viết", + "show-results-as-topics": "Kết quả dạng chủ đề", + "show-results-as-posts": "Kết quả dạng bài đăng", "see-more-results": "Xem thêm kết quả (%1)", "search-in-category": "Tìm kiếm trong \"%1\"" } \ No newline at end of file diff --git a/public/language/vi/themes/harmony.json b/public/language/vi/themes/harmony.json index aaf7690ac6..7f48a4aa32 100644 --- a/public/language/vi/themes/harmony.json +++ b/public/language/vi/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Chủ Đề Hài Hòa", "skins": "Trang điểm", - "light": "Light", - "dark": "Dark", + "light": "Sáng", + "dark": "Tối", "collapse": "Thu gọn", "expand": "Mở rộng", "sidebar-toggle": "Chuyển Đổi Thanh Bên", diff --git a/public/language/vi/topic.json b/public/language/vi/topic.json index 6aba87f482..5e687d910d 100644 --- a/public/language/vi/topic.json +++ b/public/language/vi/topic.json @@ -69,8 +69,8 @@ "user-referenced-topic-on": "%1 đã tham khảo chủ đề này trên %3", "user-forked-topic-ago": "%1 đã rẽ nhánh chủ đề này %3", "user-forked-topic-on": "%1 đã rẽ nhánh chủ đề này trên %3", - "user-crossposted-topic-ago": "%1 crossposted this topic to %2 %3", - "user-crossposted-topic-on": "%1 crossposted this topicto %2 on %3", + "user-crossposted-topic-ago": "%1 đã đăng chéo chủ đề này lên %2 %3", + "user-crossposted-topic-on": "%1 đã đăng chéo chủ đề này lên %2 vào %3", "bookmark-instructions": "Bấm vào đây để trở lại bài đọc cuối cùng trong chủ đề này.", "flag-post": "Gắn cờ bài đăng này", "flag-user": "Gắn cờ người dùng này", @@ -105,7 +105,7 @@ "thread-tools.lock": "Khóa Chủ Đề", "thread-tools.unlock": "Mở Khóa Chủ Đề", "thread-tools.move": "Di Chuyển Chủ Đề", - "thread-tools.crosspost": "Crosspost Topic", + "thread-tools.crosspost": "Chủ Đề Đăng Chéo", "thread-tools.move-posts": "Di Chuyển Bài Viết", "thread-tools.move-all": "Di chuyển tất cả", "thread-tools.change-owner": "Đổi chủ sở hữu", @@ -135,7 +135,7 @@ "pin-modal-help": "Bạn có thể đặt ngày hết hạn cho các chủ đề được ghim tại đây. Ngoài ra, bạn có thể để trống để giữ chủ đề được ghim cho đến khi chủ đề được bỏ ghim theo cách thủ công.", "load-categories": "Đang Tải Chuyên Mục", "confirm-move": "Di chuyển", - "confirm-crosspost": "Cross-post", + "confirm-crosspost": "Đăng chéo", "confirm-fork": "Chia nhánh", "bookmark": "Dấu trang", "bookmarks": "Dấu trang", @@ -145,7 +145,7 @@ "loading-more-posts": "Tải Thêm Bài Đăng", "move-topic": "Di Chuyển Chủ Đề", "move-topics": "Di Chuyển Chủ Đề", - "crosspost-topic": "Cross-post Topic", + "crosspost-topic": "Chủ Đề Đăng Chéo", "move-post": "Di chuyển bài đăng", "post-moved": "Đã di chuyển bài đăng!", "fork-topic": "Tạo bản sao chủ đề", @@ -168,9 +168,9 @@ "move-topic-instruction": "Chọn danh mục nhắm đến và sau đó nhấp vào di chuyển", "change-owner-instruction": "Bấm vào bài viết bạn muốn chỉ định cho người dùng khác", "manage-editors-instruction": "Quản lý những người dùng có thể chỉnh sửa bài đăng này bên dưới.", - "crossposts.instructions": "Select one or more categories to cross-post to. Topic(s) will be accessible from the original category and all cross-posted categories.", - "crossposts.listing": "This topic has been cross-posted to the following local categories:", - "crossposts.none": "This topic has not been cross-posted to any additional categories", + "crossposts.instructions": "Chọn một hoặc nhiều danh mục để đăng chéo bài viết. Chủ đề sẽ được truy cập từ danh mục gốc và tất cả các danh mục được đăng chéo.", + "crossposts.listing": "Chủ đề này đã được đăng tải chéo lên các chuyên mục nội bộ sau:", + "crossposts.none": "Chủ đề này chưa được đăng tải chéo lên bất kỳ chuyên mục nào khác.", "composer.title-placeholder": "Nhập tiêu đề chủ đề của bạn tại đây...", "composer.handle-placeholder": "Nhập tên/xử lý của bạn ở đây", "composer.hide": "Ẩn", @@ -182,7 +182,7 @@ "composer.replying-to": "Đang trả lời %1", "composer.new-topic": "Chủ đề mới", "composer.editing-in": "Đang sửa bài đăng trong %1", - "composer.untitled-topic": "Untitled Topic", + "composer.untitled-topic": "Chủ Đề Không Có Tiêu Đề", "composer.uploading": "đang tải lên...", "composer.thumb-url-label": "Dán URL hình mô tả chủ đề", "composer.thumb-title": "Thêm ảnh mô tả cho chủ đề này", @@ -225,7 +225,7 @@ "no-more-next-post": "Bạn không có bài viết nào khác trong chủ đề này", "open-composer": "Mở composer", "post-quick-reply": "Trả lời nhanh", - "post-quick-create": "Quick post", + "post-quick-create": "Đăng nhanh", "navigator.index": "Bài đăng %1 trên %2", "navigator.unread": "%1 chưa đọc", "upvote-post": "Ủng hộ bài đăng", @@ -235,7 +235,7 @@ "thumb-image": "Ảnh thumbnail chủ đề", "announcers": "Chia sẻ", "announcers-x": "Chia sẻ (%1)", - "guest-cta.title": "Hello! It looks like you're interested in this conversation, but you don't have an account yet.", - "guest-cta.message": "Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.", - "guest-cta.closing": "With your input, this post could be even better 💗" + "guest-cta.title": "Chào bạn! Có vẻ như bạn quan tâm đến cuộc trò chuyện này, nhưng bạn chưa có tài khoản.", + "guest-cta.message": "Bạn cảm thấy mệt mỏi vì phải cuộn qua cùng một bài đăng mỗi lần truy cập? Khi đăng ký tài khoản, bạn sẽ luôn quay lại đúng vị trí bạn đã xem trước đó và có thể chọn nhận thông báo về các bình luận mới (qua email hoặc thông báo đẩy). Bạn cũng có thể lưu lại các bài đăng yêu thích và bình chọn cho các bài đăng để thể hiện sự ủng hộ của mình đối với các thành viên khác trong cộng đồng.", + "guest-cta.closing": "Với sự đóng góp của bạn, bài viết này sẽ còn tuyệt vời hơn nữa 💗" } \ No newline at end of file diff --git a/public/language/vi/user.json b/public/language/vi/user.json index f72de65983..def098d741 100644 --- a/public/language/vi/user.json +++ b/public/language/vi/user.json @@ -105,7 +105,7 @@ "show-email": "Hiện Email Của Tôi", "show-fullname": "Hiển Thị Tên Đầy Đủ Của Tôi", "restrict-chats": "Chỉ cho phép tin nhắn từ người tôi theo dõi", - "disable-incoming-chats": "Disable incoming chat messages ", + "disable-incoming-chats": "Tắt tin nhắn trò chuyện đến ", "chat-allow-list": "Cho phép tin nhắn từ những người dùng theo dõi", "chat-deny-list": "Từ chối tin nhắn từ những người dùng theo dõi", "chat-list-add-user": "Thêm người", @@ -132,8 +132,8 @@ "email-hidden": "Ẩn Email", "hidden": "đã ẩn", "paginate-description": "Phân trang chủ đề và bài đăng thay vì sử dụng cuộn vô hạn", - "topics-per-page": "Topics per page", - "posts-per-page": "Posts per page", + "topics-per-page": "Số chủ đề mỗi trang", + "posts-per-page": "Số bài viết mỗi trang", "category-topic-sort": "Sắp xếp chủ đề danh mục", "topic-post-sort": "Sắp xếp bài đăng chủ đề", "max-items-per-page": "Tối đa %1", @@ -149,8 +149,8 @@ "notification-type-web": "Web", "notification-type-email": "Email", "browsing": "Cài Đặt Lướt Xem", - "unread.cutoff": "Unread cutoff (Maximum %1 days)", - "unread.cutoff-help": "Topics will be marked read if they have not been updated within this number of days.", + "unread.cutoff": "Hạn chót cho tin nhắn chưa đọc (Tối đa 1% ngày)", + "unread.cutoff-help": "Các chủ đề sẽ được đánh dấu là đã đọc nếu chúng không được cập nhật trong vòng số ngày này.", "open-links-in-new-tab": "Mở liên kết bên ngoài trong tab mới.", "enable-topic-searching": "Bật Tìm Kiếm Trong Chủ Đề", "topic-search-help": "Nếu bật, tìm kiếm trong chủ đề sẽ thay thế tìm kiếm của trình duyệt và cho phép bạn tìm kiếm trong toàn bộ chủ đề, thay vì chỉ tìm kiếm nội dung đang hiện thị trên màn hình", @@ -179,7 +179,7 @@ "sso.dissociate": "Tách khỏi", "sso.dissociate-confirm-title": "Xác nhận việc tách khỏi", "sso.dissociate-confirm": "Bạn có chắc chắn muốn tách tài khoản của mình khỏi %1?", - "info.invited-by": "Invited by", + "info.invited-by": "Được mời bởi", "info.latest-flags": "Gắn cờ mới nhất", "info.profile": "Hồ sơ", "info.post": "Bài viết", diff --git a/public/language/vi/world.json b/public/language/vi/world.json index 7191c7ac5f..77a23d73a5 100644 --- a/public/language/vi/world.json +++ b/public/language/vi/world.json @@ -1,11 +1,13 @@ { "name": "Thế giới", "latest": "Latest", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", + "latest-local": "Latest (Local)", + "latest-all": "Mới nhất (Tất cả)", + "popular-day": "Phổ biến (Ngày)", + "popular-week": "Phổ biến (Tuần)", + "popular-month": "Phổ biến (Tháng)", + "popular-year": "Phổ biến (Năm)", + "popular-alltime": "Phổ biến (Mọi thời đại)", "recent": "Tất cả", "help": "Trợ giúp", @@ -16,10 +18,12 @@ "help.federating": "Tương tự như vậy, nếu người dùng bên ngoài diễn đàn này bắt đầu theo dõi bạn, thì bài đăng của bạn cũng sẽ bắt đầu xuất hiện trên các ứng dụng và trang web đó.", "help.next-generation": "Đây là thế hệ mạng xã hội kế tiếp, hãy bắt đầu đóng góp ngay hôm nay!", - "onboard.title": "Cửa sổ của bạn đến với liên đoàn...", - "onboard.what": "Đây là danh mục được cá nhân hóa của bạn chỉ bao gồm nội dung được tìm thấy bên ngoài diễn đàn này. Việc nội dung nào đó có hiển thị trên trang này hay không tùy thuộc vào việc bạn có theo dõi họ hay không hoặc liệu bài đăng đó có được chia sẻ bởi người mà bạn theo dõi hay không.", - "onboard.why": "Có rất nhiều điều diễn ra bên ngoài diễn đàn này và không phải tất cả đều phù hợp với sở thích của bạn. Đó là lý do tại sao theo dõi mọi người là cách tốt nhất để báo hiệu rằng bạn muốn biết thêm thông tin từ ai đó.", - "onboard.how": "Trong thời gian chờ đợi, bạn có thể nhấp vào các nút tắt ở trên cùng để xem diễn đàn này biết thêm những gì và bắt đầu khám phá một số nội dung mới!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Tìm danh mục...", + "see-more": "Xem nhiều hơn", + "see-less": "Xem ít hơn" } \ No newline at end of file diff --git a/public/language/zh-CN/admin/advanced/database.json b/public/language/zh-CN/admin/advanced/database.json index 575fbdbf1b..d1a9894c2e 100644 --- a/public/language/zh-CN/admin/advanced/database.json +++ b/public/language/zh-CN/admin/advanced/database.json @@ -22,7 +22,7 @@ "mongo.bytes-out": "字节输出", "mongo.num-requests": "请求数量", "mongo.raw-info": "MongoDB 原始信息", - "mongo.unauthorized": "NodeBB 无法查询 MongoDB 数据库的相关统计数据。请确保 NodeBB 使用的用户含有"admin"数据库的"clusterMonitor"角色。", + "mongo.unauthorized": "NodeBB 无法查询 MongoDB 数据库以获取相关统计信息。请确保 NodeBB 使用的用户在 "admin" 数据库中具有 "clusterMonitor" 角色。", "redis": "Redis", "redis.version": "Redis 版本", diff --git a/public/language/zh-CN/admin/advanced/jobs.json b/public/language/zh-CN/admin/advanced/jobs.json new file mode 100644 index 0000000000..7159567c23 --- /dev/null +++ b/public/language/zh-CN/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "任务", + "job-name": "任务名", + "schedule": "调度", + "next-run": "下次执行", + "last-duration": "上次持续时间", + "running": "执行中", + "active": "启用" +} \ No newline at end of file diff --git a/public/language/zh-CN/admin/dashboard.json b/public/language/zh-CN/admin/dashboard.json index 9b29f2eae1..7a3a615e2e 100644 --- a/public/language/zh-CN/admin/dashboard.json +++ b/public/language/zh-CN/admin/dashboard.json @@ -6,12 +6,13 @@ "new-users": "新用户", "posts": "发帖", "topics": "主题", - "remote-posts": "Remote Posts", - "remote-topics": "Remote Topics", + "remote-posts": "远程帖子", + "remote-topics": "远程主题", + "messages": "消息", "page-views-seven": "最近7天", "page-views-thirty": "最近30天", "page-views-last-day": "最近24小时", - "page-views-custom": "自定义日期范围", + "page-views-custom": "自定义范围", "page-views-custom-start": "范围开始", "page-views-custom-end": "范围结束", "page-views-custom-help": "输入您要查看的网页浏览日期范围。 如果没有日期选择器可用,则接受的格式是 YYYY-MM-DD", @@ -30,8 +31,8 @@ "keep-updated": "请确保您已及时更新 NodeBB 以获得最新的安全补丁与 Bug 修复。", "up-to-date": "您正在使用最新版本", "upgrade-available": "新版本(v%1)已发布。建议您升级您的 NodeBB 。", - "prerelease-upgrade-available": "这是一个过时的预发布版本的 NodeBB 。一个新版本(v%1)已经发布。考虑升级您的 NodeBB 。", - "prerelease-warning": "这是NodeBB的一个预发布版本。可能会出现不平衡。", + "prerelease-upgrade-available": "这是 NodeBB 的过时预发布版本。新版本(v%1)已发布。请考虑升级您的 NodeBB。", + "prerelease-warning": "这是 NodeBB 的预发布版本。可能存在意外的错误。", "fallback-emailer-not-found": "备用邮箱发送器没有找到!", "running-in-development": "论坛正以开发模式运行。处于该模式的论坛可能存在潜在的漏洞,请联系您的论坛管理员。", "latest-lookup-failed": "查询NodeBB的最新版本失败", diff --git a/public/language/zh-CN/admin/development/info.json b/public/language/zh-CN/admin/development/info.json index c6df060106..00540f4355 100644 --- a/public/language/zh-CN/admin/development/info.json +++ b/public/language/zh-CN/admin/development/info.json @@ -8,7 +8,7 @@ "nodejs": "nodejs", "online": "在线", "git": "git", - "process-memory": "rss/heap used", + "process-memory": "RSS / 堆已用", "system-memory": "系统内存", "used-memory-process": "进程使用的内存", "used-memory-os": "已使用系统内存", diff --git a/public/language/zh-CN/admin/manage/categories.json b/public/language/zh-CN/admin/manage/categories.json index f2642878d9..7d865efe3c 100644 --- a/public/language/zh-CN/admin/manage/categories.json +++ b/public/language/zh-CN/admin/manage/categories.json @@ -55,7 +55,7 @@ "select-category": "选择版块", "set-parent-category": "设置父版块", - "privileges.description": "You can configure the access control privileges for portions of the site in this section. Privileges can be granted on a per-user or a per-group basis.", + "privileges.description": "在此部分中,您可以为网站的各个区域配置访问控制权限。权限可按用户或按用户组授予。", "privileges.category-selector": "为该版块配置权限:", "privileges.warning": "注意:权限设置会立即生效。 调整这些设置后,无需保存。", "privileges.section-viewing": "查看权限", diff --git a/public/language/zh-CN/admin/manage/custom-reasons.json b/public/language/zh-CN/admin/manage/custom-reasons.json index 90a2e620af..61de8db44c 100644 --- a/public/language/zh-CN/admin/manage/custom-reasons.json +++ b/public/language/zh-CN/admin/manage/custom-reasons.json @@ -1,16 +1,16 @@ { - "title": "Manage Custom Reasons", - "create-reason": "Create Reason", - "edit-reason": "Edit Reason", - "reasons-help": "Reasons are predefined explanations used when banning or muting users, or when rejecting posts in the post queue.", - "reason-title": "Title", - "reason-type": "Type", - "reason-body": "Body", - "reason-all": "All", - "reason-ban": "Ban", - "reason-mute": "Mute", - "reason-post-queue": "Post Queue", - "reason-type-help": "The type of action this reason applies to. If 'All' is selected, this reason will be available for all action types.", - "custom-reasons-saved": "Custom reasons saved successfully", - "delete-reason-confirm-x": "Are you sure you want to delete the custom reason with the title %1?" + "title": "管理自定义原因", + "create-reason": "创建原因", + "edit-reason": "编辑原因", + "reasons-help": "原因是预先定义的解释,用于在封禁或禁言用户时,或在发帖队列中拒绝帖子时使用。", + "reason-title": "标题", + "reason-type": "类型", + "reason-body": "正文", + "reason-all": "所有", + "reason-ban": "封禁", + "reason-mute": "禁言", + "reason-post-queue": "发帖队列", + "reason-type-help": "此原因适用的操作类型。若选中“全部”,则该原因将适用于所有操作类型。", + "custom-reasons-saved": "自定义原因已成功保存", + "delete-reason-confirm-x": "您确定您要删除标题为 %1 的自定义原因吗?" } \ No newline at end of file diff --git a/public/language/zh-CN/admin/manage/privileges.json b/public/language/zh-CN/admin/manage/privileges.json index c65fe192ea..795cf2ada8 100644 --- a/public/language/zh-CN/admin/manage/privileges.json +++ b/public/language/zh-CN/admin/manage/privileges.json @@ -29,7 +29,7 @@ "access-topics": "访问主题", "create-topics": "创建主题", "reply-to-topics": "回复主题", - "crosspost-topics": "Cross-post Topics", + "crosspost-topics": "交叉发布主题", "schedule-topics": "定时主题", "tag-topics": "标签主题", "edit-posts": "修改回复", diff --git a/public/language/zh-CN/admin/manage/users.json b/public/language/zh-CN/admin/manage/users.json index 9d8ad9e764..d62f412fc7 100644 --- a/public/language/zh-CN/admin/manage/users.json +++ b/public/language/zh-CN/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "每页250", "500-per-page": "每页500", + "search.help": "使用 "*" 进行部分搜索,例如 "*query"", "search.uid": "通过用户 ID", "search.uid-placeholder": "输入用户 ID 以搜索", "search.username": "通过用户名", @@ -55,7 +56,7 @@ "inactive.12-months": "12个月", "users.uid": "UID", - "users.user-id": "User ID", + "users.user-id": "用户 ID", "users.username": "用户名", "users.email": "电子邮件", "users.no-email": "(没有邮箱)", @@ -64,7 +65,7 @@ "users.validation-pending": "等待验证", "users.validation-expired": "验证过期", "users.ip": "IP", - "users.recent-ips": "Recent IPs", + "users.recent-ips": "最近访问 IP", "users.postcount": "发帖数", "users.reputation": "声望", "users.flags": "举报", diff --git a/public/language/zh-CN/admin/menu.json b/public/language/zh-CN/admin/menu.json index 61aaf0fd6d..ffa4c8e0ef 100644 --- a/public/language/zh-CN/admin/menu.json +++ b/public/language/zh-CN/admin/menu.json @@ -48,13 +48,13 @@ "settings.page-title": "%1 设置", - "section-federation": "Federation", - "federation/general": "General", - "federation/content": "Content", - "federation/rules": "Categorization", - "federation/relays": "Relays", - "federation/pruning": "Storage", - "federation/safety": "Trust & Safety", + "section-federation": "“联邦”", + "federation/general": "通用", + "federation/content": "内容", + "federation/rules": "分类", + "federation/relays": "中继服务", + "federation/pruning": "存储", + "federation/safety": "信任与安全", "section-appearance": "界面", "appearance/themes": "主题", @@ -78,6 +78,7 @@ "advanced/logs": "日志", "advanced/errors": "错误", "advanced/cache": "缓存", + "advanced/jobs": "任务", "development/logger": "记录器", "development/info": "信息", diff --git a/public/language/zh-CN/admin/settings/activitypub.json b/public/language/zh-CN/admin/settings/activitypub.json index 9ad8afaffe..75308dab20 100644 --- a/public/language/zh-CN/admin/settings/activitypub.json +++ b/public/language/zh-CN/admin/settings/activitypub.json @@ -46,9 +46,10 @@ "server.filter-help-hostname": "请在下面输入实例主机名(如 example.org ),中间用换行符隔开。", "server.filter-allow-list": "将其用作允许列表", - "content.outgoing": "Outgoing", - "content.summary-limit": "Character count after which a summary is generated", - "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", - "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.outgoing": "外部", + "content.summary-limit": "生成摘要后的字符计数", + "content.summary-limit-help": "当联合输出内容超过此字符限制时,将生成 摘要 ,包含该限制前的所有完整句子。(默认值:500)", + "content.break-string": "注释/文章分隔符", + "content.break-string-help": "此分隔符可由高级用户在撰写新主题时手动插入。它指示 NodeBB 将该分隔符之前的内容作为摘要的一部分。若未使用此字符串,则采用字符计数备用方案。(默认值:[...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/zh-CN/admin/settings/email.json b/public/language/zh-CN/admin/settings/email.json index bb3e6b732a..8b8829dae3 100644 --- a/public/language/zh-CN/admin/settings/email.json +++ b/public/language/zh-CN/admin/settings/email.json @@ -30,20 +30,20 @@ "smtp-transport.pool-help": "池式连接可防止 NodeBB 为每封邮件创建新的连接。此选项仅适用于启用SMTP传输的情况下。", "smtp-transport.allow-self-signed": "允许自签名证书", "smtp-transport.allow-self-signed-help": "启用此设置可允许您使用自签名或无效的 TLS 证书。", - "smtp-transport.test-success": "SMTP Test email sent successfully.", + "smtp-transport.test-success": "SMTP 测试邮件已成功发送。", "template": "编辑电子邮件模板", "template.select": "选择电子邮件模板", "template.revert": "还原为初始模板", - "test-smtp-settings": "Test SMTP Settings", + "test-smtp-settings": "测试 SMTP 设置", "testing": "电子邮件测试", - "testing.success": "Test Email Sent.", + "testing.success": "测试邮件已发送。", "testing.select": "选择电子邮件模板", "testing.send": "发送测试电子邮件", - "testing.send-help-plugin": "\"%1\" will be used to send test emails.", - "testing.send-help-smtp": "SMTP transport is enabled and will be used to send emails.", - "testing.send-help-no-plugin": "No emailer plugin is installed to send emails, nodemailer will be used by default.", - "testing.send-help": "The test email will be sent to the currently logged in user's email address using the saved settings on this page. ", + "testing.send-help-plugin": "\"%1\" 将用于发送测试邮件。", + "testing.send-help-smtp": "已启用 SMTP 传输协议,并将用于发送电子邮件。", + "testing.send-help-no-plugin": "当前未安装任何用于发送邮件的插件,系统将默认使用 nodemailer。", + "testing.send-help": "测试邮件将根据本页保存的设置,发送到当前已登录用户的电子邮箱地址。", "subscriptions": "电子邮件摘要", "subscriptions.disable": "禁用电子邮件摘要", "subscriptions.hour": "摘要小时", diff --git a/public/language/zh-CN/admin/settings/general.json b/public/language/zh-CN/admin/settings/general.json index cd6cc33bac..a6b4916b8e 100644 --- a/public/language/zh-CN/admin/settings/general.json +++ b/public/language/zh-CN/admin/settings/general.json @@ -7,7 +7,7 @@ "title.short-placeholder": "如果没有指定短标题,将会使用站点标题", "title.url": "标题链接地址", "title.url-placeholder": "网站标题链接", - "title.url-help": "当标题被点击时,将向用户发送该地址。如果留空,用户将跳转到论坛索引页面。注意:这不是在电子邮件中使用的外部URL,这由config.json中的url属性设置。", + "title.url-help": "点击标题时,将用户重定向至此地址。若留空,用户将被重定向至论坛首页。注意:此处并非用于电子邮件等场景的外部网址。该网址由 config.json 文件中的 url 属性设定。", "title.name": "您的社区名称", "title.show-in-header": "在顶部显示站点标题", "browser-title": "浏览器标题", @@ -18,7 +18,7 @@ "description": "站点描述", "keywords": "站点关键字", "keywords-placeholder": "描述您的社区的关键字(以逗号分隔)", - "logo-and-icons": "网站徽标与图标", + "logo-and-icons": "媒体与品牌建设", "logo.image": "图像", "logo.image-placeholder": "要在论坛标题上显示的 Logo 的路径", "logo.upload": "上传", @@ -35,6 +35,8 @@ "touch-icon.help": "推荐的尺寸和格式:512x512,仅限PNG格式。如果没有指定触摸图标,NodeBB将回退到站点图标。", "maskable-icon": "可遮蔽(主屏)图标", "maskable-icon.help": "推荐的尺寸和格式:512x512,仅限PNG格式。如果没有指定可遮蔽图标,NodeBB将回退到触摸图标。", + "screenshot": "屏幕截图", + "screenshot.help": "推荐尺寸和格式:320px 至 3480px 之间,仅限 JPG 和 PNG 格式。如果未指定截图,NodeBB 将使用通用截图作为替代", "outgoing-links": "站外链接", "outgoing-links.warning-page": "使用站外链接警告页", "search": "搜索", @@ -47,17 +49,17 @@ "background-color": "背景色", "background-color-help": "当网站安装为 PWA 时用于启动屏幕背景的颜色", "undo-timeout": "撤销超时", - "undo-timeout-help": "部分操作,例如移动主题,将允许版主在一定时间内撤销其操作。设置为 0 可完全禁用撤消。", + "undo-timeout-help": "某些操作(例如移动主题)允许版主在一定时间内撤销该操作。将该值设为 0 可完全禁用撤销功能。", "topic-tools": "主题工具", "home-page": "主页", "home-page-route": "主页路由", - "home-page-description": "选择用户导航到论坛根 URL 时显示的页面。", + "home-page-description": "选择用户访问论坛根 URL 时显示的页面。", "custom-route": "自定义路由", "allow-user-home-pages": "允许用户主页", "home-page-title": "首页标题(默认“Home”)", "default-language": "默认语言", "auto-detect": "自动检测游客的语言设置", - "default-language-help": "默认语言会决定所有用户的语言设定。
单一用户可以各自在帐户设置中覆盖此项设定。", + "default-language-help": "默认语言决定了所有访问您论坛的用户的语言设置。
用户可以在其账号设置页面中覆盖默认语言。", "post-sharing": "帖子分享", - "info-plugins-additional": "插件可以增加可选的用于分享帖子的网络。" + "info-plugins-additional": "插件可以添加额外的社交网络,用于分享帖子。" } \ No newline at end of file diff --git a/public/language/zh-CN/admin/settings/notifications.json b/public/language/zh-CN/admin/settings/notifications.json index dd036f1271..764a7e0538 100644 --- a/public/language/zh-CN/admin/settings/notifications.json +++ b/public/language/zh-CN/admin/settings/notifications.json @@ -4,6 +4,6 @@ "welcome-notification-link": "欢迎通知链接", "welcome-notification-uid": "用户欢迎通知 (UID)", "post-queue-notification-uid": "发布队列用户(UID)", - "notification-delay": "Delay for sending notification emails (seconds)", - "notification-delay-help": "If the user has read the notification within this time, the email will not be sent.
Default: 60 seconds." + "notification-delay": "发送通知邮件的延迟时间(秒)", + "notification-delay-help": "如果用户在此时间内已阅读通知,则不会发送电子邮件。
默认值:60秒。" } \ No newline at end of file diff --git a/public/language/zh-CN/admin/settings/uploads.json b/public/language/zh-CN/admin/settings/uploads.json index 08115d299e..991f3565e8 100644 --- a/public/language/zh-CN/admin/settings/uploads.json +++ b/public/language/zh-CN/admin/settings/uploads.json @@ -40,7 +40,7 @@ "default-avatar": "访客默认头像", "upload": "上传", "profile-image-dimension": "个人资料相片尺寸", - "profile-image-dimension-help": "(in pixels, default: 200 pixels)", + "profile-image-dimension-help": "(单位:像素,默认值:200 像素)", "max-profile-image-size": "个人资料相片最大大小", "max-profile-image-size-help": "(单位 KiB ,默认 256 KiB)", "max-cover-image-size": "最大封面图片文件大小", diff --git a/public/language/zh-CN/admin/settings/user.json b/public/language/zh-CN/admin/settings/user.json index ff2acbaa24..7858667fff 100644 --- a/public/language/zh-CN/admin/settings/user.json +++ b/public/language/zh-CN/admin/settings/user.json @@ -6,20 +6,20 @@ "allow-login-with.username-email": "用户名或者邮箱", "allow-login-with.username": "仅限用户名", "account-settings": "用户设置", - "gdpr-enabled": "启用通用数据保护条例(GDPR)许可的个人信息收集", - "gdpr-enabled-help": "当启用时,所有的新注册用户需要明确同意允许数据采集和在通用数据保护协议(GDPR)保护下的使用。注意:开启GDPR不一定要之前已经存在的用户同意。在这之前,您需要去安装GDPR插件。", + "gdpr-enabled": "启用《通用数据保护条例》(GDPR)的同意收集功能", + "gdpr-enabled-help": "启用此功能后,所有新注册用户都必须根据《通用数据保护条例》(GDPR)明确同意数据收集和使用。注意:启用GDPR不会强制现有用户提供同意。若要实现此功能,您需要安装GDPR插件。", "disable-username-changes": "禁用修改用户名", "disable-email-changes": "禁用修改邮箱", "disable-password-changes": "禁用修改密码", - "allow-account-deletion": "允许消除帐号", + "allow-account-deletion": "允许删除账号", "hide-fullname": "隐藏用户的全名", "hide-email": "隐藏用户的电子邮箱", - "show-fullname-as-displayname": "如果可以,把用户的全名作为他们的显示名称。", + "show-fullname-as-displayname": "如果可用,则显示用户的全名作为其显示名称", "themes": "主题", - "disable-user-skins": "阻止用户选择自定义皮肤", + "disable-user-skins": "禁止用户选择自定义皮肤", "account-protection": "帐号保护", "admin-relogin-duration": "管理员无操作自动退出时长 (分钟)", - "admin-relogin-duration-help": "访问管理面板一段时间后需要重新登录以保证管理面板的安全,设置为0以禁用。", + "admin-relogin-duration-help": "在管理员区域停留一定时间后,系统将要求重新登录;将该值设为 0 可禁用此功能", "login-attempts": "每小时尝试登录次数", "login-attempts-help": "如果用户的尝试登录次数超过此界限,该帐号将会被被锁定预设的时间。", "lockout-duration": "帐户锁定时间(分钟)", diff --git a/public/language/zh-CN/admin/settings/web-crawler.json b/public/language/zh-CN/admin/settings/web-crawler.json index 510522f5d3..17e5574954 100644 --- a/public/language/zh-CN/admin/settings/web-crawler.json +++ b/public/language/zh-CN/admin/settings/web-crawler.json @@ -5,7 +5,7 @@ "disable-rss-feeds": "禁用 RSS 订阅", "disable-sitemap-xml": "禁用 Sitemap.xml", "sitemap-topics": "要在 Stemap 中展示的主题数量", - "sitemap-cache-duration-hours": "Sitemap Cache Duration (hours)", + "sitemap-cache-duration-hours": "网站地图缓存时长(小时)", "clear-sitemap-cache": "清除 Sitemap 缓存", "view-sitemap": "查看 Sitemap" } \ No newline at end of file diff --git a/public/language/zh-CN/aria.json b/public/language/zh-CN/aria.json index 44960de6dc..232f953964 100644 --- a/public/language/zh-CN/aria.json +++ b/public/language/zh-CN/aria.json @@ -6,5 +6,5 @@ "user-watched-tags": "用户关注的标签", "delete-upload-button": "删除上传按钮", "group-page-link-for": "%1 的群组页面链接", - "show-crossposts": "Show Cross-posts" + "show-crossposts": "显示交叉发布" } \ No newline at end of file diff --git a/public/language/zh-CN/category.json b/public/language/zh-CN/category.json index 765adb544f..c854af070d 100644 --- a/public/language/zh-CN/category.json +++ b/public/language/zh-CN/category.json @@ -1,8 +1,8 @@ { "category": "版块", "subcategories": "子版块", - "uncategorized": "World", - "uncategorized.description": "Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.", + "uncategorized": "世界", + "uncategorized.description": "本论坛之外的主题。此处表达的观点和意见可能不代表本论坛及其成员的立场。", "handle.description": "此版块可通过社交网络公开平台使用用户名 %1 进行关注", "new-topic-button": "发表主题", "guest-login-post": "登录以发布", diff --git a/public/language/zh-CN/error.json b/public/language/zh-CN/error.json index 4f7360b352..f34a214df8 100644 --- a/public/language/zh-CN/error.json +++ b/public/language/zh-CN/error.json @@ -1,5 +1,6 @@ { "invalid-data": "无效数据", + "invalid-config-field-value": "配置字段“%1”的值无效:%2", "invalid-json": "无效 JSON", "wrong-parameter-type": "属性 `%1` 要求是类型 %3 的值,却收到了 %2", "required-parameters-missing": "此 API 调用必需参数缺少了:%1", @@ -32,7 +33,7 @@ "invalid-path": "无效的路径", "folder-exists": "文件夹已存在", "invalid-pagination-value": "无效的分页数值,必须介于 %1 和 %2 之间", - "invalid-unread-cutoff": "Invalid unread cutoff value, must be at least 1 and at most %1", + "invalid-unread-cutoff": "无效的未读截止值,必须至少为 1 且最多为 %1", "username-taken": "此用户名已被占用", "email-taken": "邮箱地址已被注册", "email-nochange": "输入的邮件地址和已存档的邮件地址相同。", diff --git a/public/language/zh-CN/global.json b/public/language/zh-CN/global.json index 049efa9730..aa43b4577c 100644 --- a/public/language/zh-CN/global.json +++ b/public/language/zh-CN/global.json @@ -137,7 +137,7 @@ "allowed-file-types": "允许的文件类型有 %1", "unsaved-changes": "您有未保存的更改,您确定您要离开么?", "reconnecting-message": "与 %1 的连接断开,我们正在尝试重连,请耐心等待", - "reconnected-message": "Reconnected to %1 successfully.", + "reconnected-message": "已成功重新连接到 %1。", "play": "播放", "cookies.message": "此网站使用 Cookies 以保障您在我们网站的最佳体验。", "cookies.accept": "知道了!", diff --git a/public/language/zh-CN/groups.json b/public/language/zh-CN/groups.json index 696596d8cf..1f5b88de8f 100644 --- a/public/language/zh-CN/groups.json +++ b/public/language/zh-CN/groups.json @@ -1,9 +1,9 @@ { - "group": "Group", + "group": "群组", "all-groups": "所有群组", "groups": "群组", "members": "成员", - "x-members": "%1 member(s)", + "x-members": "%1 位成员", "view-group": "查看群组", "owner": "群组所有者", "new-group": "创建群组", diff --git a/public/language/zh-CN/modules.json b/public/language/zh-CN/modules.json index 8ef99fef8f..0587f3ad93 100644 --- a/public/language/zh-CN/modules.json +++ b/public/language/zh-CN/modules.json @@ -82,7 +82,7 @@ "composer.hide-preview": "隐藏预览", "composer.help": "帮助", "composer.user-said-in": "%1 在 %2 中说:", - "composer.user-said": "%1 [said](%2):", + "composer.user-said": "%1 [说](%2):", "composer.discard": "确定想要取消此帖?", "composer.submit-and-lock": "提交并锁定", "composer.toggle-dropdown": "切换下拉菜单", diff --git a/public/language/zh-CN/notifications.json b/public/language/zh-CN/notifications.json index 289bd6d801..df2a4fd191 100644 --- a/public/language/zh-CN/notifications.json +++ b/public/language/zh-CN/notifications.json @@ -65,7 +65,7 @@ "new-register-multiple": "有 %1 条注册申请等待批准。", "flag-assigned-to-you": "举报 %1 已经被指派给您", "post-awaiting-review": "待查阅的帖子", - "topic-awaiting-review": "Topic awaiting review", + "topic-awaiting-review": "主题待审核", "profile-exported": "%1资料已导出,点击下载", "posts-exported": "%1帖子已导出,点击下载", "uploads-exported": "%1上传已导出,点击下载", diff --git a/public/language/zh-CN/themes/harmony.json b/public/language/zh-CN/themes/harmony.json index 726fb78fb3..9e215b081d 100644 --- a/public/language/zh-CN/themes/harmony.json +++ b/public/language/zh-CN/themes/harmony.json @@ -1,8 +1,8 @@ { "theme-name": "Harmony 主题", "skins": "皮肤", - "light": "Light", - "dark": "Dark", + "light": "浅色", + "dark": "深色", "collapse": "折叠", "expand": "展开", "sidebar-toggle": "侧栏滚动", diff --git a/public/language/zh-CN/topic.json b/public/language/zh-CN/topic.json index c753f1fba7..df47079cb6 100644 --- a/public/language/zh-CN/topic.json +++ b/public/language/zh-CN/topic.json @@ -225,7 +225,7 @@ "no-more-next-post": "您在此主题中没有更多的帖子了", "open-composer": "打开编辑器", "post-quick-reply": "快速回复", - "post-quick-create": "Quick post", + "post-quick-create": "快速发帖", "navigator.index": "%1 / %2", "navigator.unread": "未读 %1", "upvote-post": "顶贴", diff --git a/public/language/zh-CN/user.json b/public/language/zh-CN/user.json index 618b2878c5..b2b2c765f9 100644 --- a/public/language/zh-CN/user.json +++ b/public/language/zh-CN/user.json @@ -146,8 +146,8 @@ "upvote-notif-freq.threshold": "当被顶的数目为1, 5, 10, 25, 50, 100, 150, 200...时通知我", "upvote-notif-freq.logarithmic": "当被顶的数目为10, 100, 1000...时通知我", "upvote-notif-freq.disabled": "任何时候都不要通知我", - "notification-type-web": "Web", - "notification-type-email": "Email", + "notification-type-web": "网站", + "notification-type-email": "邮件", "browsing": "浏览设置", "unread.cutoff": "未读邮件截止时间(最多 %1 天)", "unread.cutoff-help": "若主题在指定天数内未更新,则会被标记为已读。", diff --git a/public/language/zh-CN/world.json b/public/language/zh-CN/world.json index 524760099f..4e2f056e85 100644 --- a/public/language/zh-CN/world.json +++ b/public/language/zh-CN/world.json @@ -1,11 +1,13 @@ { "name": "世界", - "latest": "最新", - "popular-day": "Popular (Day)", - "popular-week": "Popular (Week)", - "popular-month": "Popular (Month)", - "popular-year": "Popular (Year)", - "popular-alltime": "Popular (All Time)", + "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "最新(全部)", + "popular-day": "热门(按天)", + "popular-week": "热门(按周)", + "popular-month": "热门(按月)", + "popular-year": "热门(按年)", + "popular-alltime": "热门(所有时间)", "recent": "全部", "help": "帮助", @@ -16,10 +18,12 @@ "help.federating": "同样,如果本论坛以外的用户开始关注 ,那么您的帖子也会开始出现在这些应用程序和网站上。", "help.next-generation": "这是新一代的社交媒体,从今天开始,贡献力量吧!", - "onboard.title": "您通往联邦宇宙的窗口...", - "onboard.what": "这是您的个性化版块,只包含本论坛以外的内容。内容是否显示在本页取决于您是否关注他们,或者该帖子是否由您关注的人分享。", - "onboard.why": "论坛之外的事情很多,而且并非所有事情都与您的兴趣相关。因此,关注他人是表明您想从某人那里了解更多信息的最佳方式。", - "onboard.how": "在此期间,您可以点击顶部的快捷按钮,了解本论坛的其他内容,并开始发现一些新内容!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "查找版块..." + "category-search": "查找版块...", + "see-more": "显示更多", + "see-less": "显示更少" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/advanced/jobs.json b/public/language/zh-TW/admin/advanced/jobs.json new file mode 100644 index 0000000000..896b07930a --- /dev/null +++ b/public/language/zh-TW/admin/advanced/jobs.json @@ -0,0 +1,9 @@ +{ + "jobs": "Jobs", + "job-name": "Job Name", + "schedule": "Schedule", + "next-run": "Next Run", + "last-duration": "Last Duration", + "running": "Running", + "active": "Active" +} \ No newline at end of file diff --git a/public/language/zh-TW/admin/dashboard.json b/public/language/zh-TW/admin/dashboard.json index 6d9ccd453d..747639f151 100644 --- a/public/language/zh-TW/admin/dashboard.json +++ b/public/language/zh-TW/admin/dashboard.json @@ -8,10 +8,11 @@ "topics": "主題", "remote-posts": "Remote Posts", "remote-topics": "Remote Topics", + "messages": "Messages", "page-views-seven": "最近7天", "page-views-thirty": "最近30天", "page-views-last-day": "最近24小時", - "page-views-custom": "自定義日期範圍", + "page-views-custom": "Custom Range", "page-views-custom-start": "範圍開始", "page-views-custom-end": "範圍結束", "page-views-custom-help": "輸入您要查看的網頁瀏覽日期範圍。 如果沒有日期選擇器可用,則接受的格式是 YYYY-MM-DD", diff --git a/public/language/zh-TW/admin/manage/users.json b/public/language/zh-TW/admin/manage/users.json index eba29d39ea..2d8f267d3f 100644 --- a/public/language/zh-TW/admin/manage/users.json +++ b/public/language/zh-TW/admin/manage/users.json @@ -40,6 +40,7 @@ "250-per-page": "每頁250", "500-per-page": "每頁500", + "search.help": "Use "*" to make partial searches, for example "*query"", "search.uid": "通過使用者ID", "search.uid-placeholder": "搜尋使用者ID", "search.username": "通過使用者名", diff --git a/public/language/zh-TW/admin/menu.json b/public/language/zh-TW/admin/menu.json index 1da8b11555..b1495efae2 100644 --- a/public/language/zh-TW/admin/menu.json +++ b/public/language/zh-TW/admin/menu.json @@ -78,6 +78,7 @@ "advanced/logs": "日誌", "advanced/errors": "錯誤", "advanced/cache": "快取", + "advanced/jobs": "Jobs", "development/logger": "記錄器", "development/info": "資訊", diff --git a/public/language/zh-TW/admin/settings/activitypub.json b/public/language/zh-TW/admin/settings/activitypub.json index 9718851b7d..3a6e0f137a 100644 --- a/public/language/zh-TW/admin/settings/activitypub.json +++ b/public/language/zh-TW/admin/settings/activitypub.json @@ -50,5 +50,6 @@ "content.summary-limit": "Character count after which a summary is generated", "content.summary-limit-help": "When content is federated out that exceeds this character count, a summary is generated, comprising of all complete sentences prior to this limit. (Default: 500)", "content.break-string": "Note/Article Delimiter", - "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])" + "content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the summary. If this string is not used, then the character count fallback applies. (Default: [...])", + "content.world-default-cid": "Default category ID for "World" page composer" } \ No newline at end of file diff --git a/public/language/zh-TW/admin/settings/general.json b/public/language/zh-TW/admin/settings/general.json index 992143a90b..a438f177ee 100644 --- a/public/language/zh-TW/admin/settings/general.json +++ b/public/language/zh-TW/admin/settings/general.json @@ -18,7 +18,7 @@ "description": "Site Description", "keywords": "網站關鍵字", "keywords-placeholder": "描述您的社區的關鍵字,以逗號分隔", - "logo-and-icons": "Site Logo & Icons", + "logo-and-icons": "Media & Branding", "logo.image": "圖檔", "logo.image-placeholder": "要在論壇標題上顯示的 Logo 的路徑", "logo.upload": "上傳", @@ -35,6 +35,8 @@ "touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "maskable-icon": "Maskable (Homescreen) Icon", "maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.", + "screenshot": "Screenshot", + "screenshot.help": "Recommended size and format: between 320px and 3480px, JPG and PNG format only. If no screenshot is specified, NodeBB will fall back to a generic screenshot", "outgoing-links": "站外連結", "outgoing-links.warning-page": "使用站外連結警告頁", "search": "Search", diff --git a/public/language/zh-TW/error.json b/public/language/zh-TW/error.json index c3ce020e5f..5a2cbc4652 100644 --- a/public/language/zh-TW/error.json +++ b/public/language/zh-TW/error.json @@ -1,5 +1,6 @@ { "invalid-data": "無效資料", + "invalid-config-field-value": "Invalid value for config field \"%1\": %2", "invalid-json": "無效 JSON", "wrong-parameter-type": "A value of type %3 was expected for property `%1`, but %2 was received instead", "required-parameters-missing": "Required parameters were missing from this API call: %1", diff --git a/public/language/zh-TW/world.json b/public/language/zh-TW/world.json index e6694bf507..2057e13d00 100644 --- a/public/language/zh-TW/world.json +++ b/public/language/zh-TW/world.json @@ -1,6 +1,8 @@ { "name": "World", "latest": "Latest", + "latest-local": "Latest (Local)", + "latest-all": "Latest (All)", "popular-day": "Popular (Day)", "popular-week": "Popular (Week)", "popular-month": "Popular (Month)", @@ -16,10 +18,12 @@ "help.federating": "Likewise, if users from outside of this forum start following you, then your posts will start appearing on those apps and websites as well.", "help.next-generation": "This is the next generation of social media, start contributing today!", - "onboard.title": "Your window to the fediverse...", - "onboard.what": "This is your personalized category made up of only content found outside of this forum. Whether something shows up in this page depends on whether you follow them, or whether that post was shared by someone you follow.", - "onboard.why": "There's a lot that goes on outside of this forum, and not all of it is relevant to your interests. That's why following people is the best way to signal that you want to see more from someone.", - "onboard.how": "In the meantime, you can click on the shortcut buttons at the top to see what else this forum knows about, and start discovering some new content!", + "onboard.title": "A world of content at your fingertips…", + "onboard.what": "Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.", + "onboard.why": "While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.", + "onboard.how": "Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.", - "category-search": "Find a category..." + "category-search": "Find a category...", + "see-more": "See more", + "see-less": "See less" } \ No newline at end of file diff --git a/public/openapi/read.yaml b/public/openapi/read.yaml index eec723b5c9..94ffd317af 100644 --- a/public/openapi/read.yaml +++ b/public/openapi/read.yaml @@ -186,6 +186,8 @@ paths: $ref: 'read/admin/advanced/cache.yaml' /api/admin/advanced/cache/dump: $ref: 'read/admin/advanced/cache/dump.yaml' + /api/admin/advanced/jobs: + $ref: 'read/admin/advanced/jobs.yaml' /api/admin/development/logger: $ref: 'read/admin/development/logger.yaml' /api/admin/development/info: diff --git a/public/openapi/read/admin/advanced/jobs.yaml b/public/openapi/read/admin/advanced/jobs.yaml new file mode 100644 index 0000000000..4a85013493 --- /dev/null +++ b/public/openapi/read/admin/advanced/jobs.yaml @@ -0,0 +1,37 @@ +get: + tags: + - admin + summary: Get cron job info + responses: + "200": + description: "" + content: + application/json: + schema: + allOf: + - type: object + properties: + jobs: + type: array + items: + type: object + properties: + name: + type: string + cronTime: + type: string + cronTimeHuman: + type: string + nextRun: + type: integer + nextRunISO: + type: integer + duration: + type: integer + durationReadable: + type: string + running: + type: boolean + active: + type: boolean + - $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps \ No newline at end of file diff --git a/public/openapi/read/admin/appearance/themes.yaml b/public/openapi/read/admin/appearance/themes.yaml index d2b2eabb68..d9e5b0e602 100644 --- a/public/openapi/read/admin/appearance/themes.yaml +++ b/public/openapi/read/admin/appearance/themes.yaml @@ -8,4 +8,34 @@ get: content: application/json: schema: - $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps \ No newline at end of file + allOf: + - type: object + properties: + themes: + type: array + items: + type: object + properties: + name: + type: string + id: + type: string + description: + type: string + screenshot: + type: string + screenshot_url: + type: string + type: + type: string + url: + type: string + baseTheme: + type: string + required: + - name + - id + - description + - type + - url + - $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps diff --git a/public/openapi/read/admin/config.yaml b/public/openapi/read/admin/config.yaml index a58405fb84..457e63fcc9 100644 --- a/public/openapi/read/admin/config.yaml +++ b/public/openapi/read/admin/config.yaml @@ -153,6 +153,8 @@ get: properties: probe: type: number + worldDefaultCid: + type: number acpLang: type: string openOutgoingLinksInNewTab: diff --git a/public/openapi/read/config.yaml b/public/openapi/read/config.yaml index 16d2043667..f4ae1dfe87 100644 --- a/public/openapi/read/config.yaml +++ b/public/openapi/read/config.yaml @@ -184,4 +184,6 @@ get: type: object properties: probe: + type: number + worldDefaultCid: type: number \ No newline at end of file diff --git a/public/openapi/read/world.yaml b/public/openapi/read/world.yaml index 450d49e362..d2cbe0b332 100644 --- a/public/openapi/read/world.yaml +++ b/public/openapi/read/world.yaml @@ -31,6 +31,9 @@ get: properties: bookmarks: type: number + selectedCategory: + $ref: ../components/schemas/CategoryObject.yaml#/CategoryObject + nullable: true showThumbs: type: boolean showTopicTools: diff --git a/public/scss/modules/bottom-sheet.scss b/public/scss/modules/bottom-sheet.scss index 9306a2ed31..f303fb1259 100644 --- a/public/scss/modules/bottom-sheet.scss +++ b/public/scss/modules/bottom-sheet.scss @@ -8,7 +8,6 @@ position: fixed!important; inset: auto 0 0 0!important; - margin: 0 -1px -1px -1px; max-height: 100dvh!important; box-shadow: 0 2px 6px rgba(0,0,0,0.35); overflow: auto; diff --git a/public/scss/skins.scss b/public/scss/skins.scss index b963dca4da..05c67fd9f7 100644 --- a/public/scss/skins.scss +++ b/public/scss/skins.scss @@ -37,6 +37,10 @@ .text-secondary { color: var(--bs-secondary-color) !important; } + + .btn-link { + background: $body-bg; + } } // fix minty buttons diff --git a/public/src/admin/appearance/themes.js b/public/src/admin/appearance/themes.js index f2a023206f..2fe0022c77 100644 --- a/public/src/admin/appearance/themes.js +++ b/public/src/admin/appearance/themes.js @@ -72,24 +72,7 @@ define('admin/appearance/themes', ['bootbox', 'translator', 'alerts'], function }); }); - socket.emit('admin.themes.getInstalled', function (err, themes) { - if (err) { - return alerts.error(err); - } - - const instListEl = $('#installed_themes'); - - if (!themes.length) { - instListEl.append($('
  • ').addClass('no-themes').translateHtml('[[admin/appearance/themes:no-themes]]')); - } else { - app.parseAndTranslate('admin/partials/theme_list', { - themes: themes, - }, function (html) { - instListEl.html(html); - highlightSelectedTheme(config['theme:id']); - }); - } - }); + highlightSelectedTheme(config['theme:id']); }; function highlightSelectedTheme(themeId) { diff --git a/public/src/admin/manage/categories.js b/public/src/admin/manage/categories.js index babdb83367..7499965385 100644 --- a/public/src/admin/manage/categories.js +++ b/public/src/admin/manage/categories.js @@ -83,15 +83,15 @@ define('admin/manage/categories', [ $('.categories').on('click', 'a[data-action]', function () { const action = this.getAttribute('data-action'); - + const cid = this.getAttribute('data-cid'); switch (action) { case 'remove': { - Categories.remove.call(this); + Categories.remove(cid); break; } case 'rename': { - Categories.rename.call(this); + Categories.rename(cid); break; } } @@ -195,21 +195,19 @@ define('admin/manage/categories', [ }); }; - Categories.remove = function () { + Categories.remove = function (cid) { bootbox.confirm('[[admin/manage/categories:alert.confirm-remove]]', (ok) => { if (ok) { - const cid = this.getAttribute('data-cid'); api.del(`/api/admin/manage/categories/${encodeURIComponent(cid)}`).then(ajaxify.refresh); } }); }; - Categories.rename = function () { + Categories.rename = function (cid) { bootbox.prompt({ title: '[[admin/manage/categories:alert.rename]]', message: '

    [[admin/manage/categories:alert.rename-help]]

    ', callback: (name) => { - const cid = this.getAttribute('data-cid'); api.post(`/api/admin/manage/categories/${encodeURIComponent(cid)}/name`, { name }).then(ajaxify.refresh); }, }); diff --git a/public/src/client/category/tools.js b/public/src/client/category/tools.js index 58a257f293..bd15ff459b 100644 --- a/public/src/client/category/tools.js +++ b/public/src/client/category/tools.js @@ -9,11 +9,16 @@ define('forum/category/tools', [ 'api', 'bootbox', 'alerts', -], function (topicSelect, threadTools, components, api, bootbox, alerts) { + 'bootstrap', +], function (topicSelect, threadTools, components, api, bootbox, alerts, bootstrap) { const CategoryTools = {}; CategoryTools.init = function (containerEl) { - topicSelect.init(updateDropdownOptions, containerEl); + topicSelect.init(updateDropdownOptions, () => { + const toggleEl = document.querySelector('.thread-tools button'); + const dropdown = new bootstrap.Dropdown(toggleEl); + dropdown.show(); + }, containerEl); handlePinnedTopicSort(); diff --git a/public/src/client/groups/details.js b/public/src/client/groups/details.js index 39395258cb..7a6d2ba6f2 100644 --- a/public/src/client/groups/details.js +++ b/public/src/client/groups/details.js @@ -209,7 +209,9 @@ define('forum/groups/details', [ // Add icon selection interface iconBtn.on('click', function () { iconSelect.init(previewIcon, function () { - iconValueEl.val(previewIcon.val()); + const icon = previewIcon.val(); + previewIcon.toggleClass('hidden', !icon || icon === 'fa-nbb-none'); + iconValueEl.val(icon); }); }); diff --git a/public/src/client/header/notifications.js b/public/src/client/header/notifications.js index fc402b8d96..94a23c9ecd 100644 --- a/public/src/client/header/notifications.js +++ b/public/src/client/header/notifications.js @@ -15,11 +15,29 @@ define('forum/header/notifications', function () { notifTrigger.each((index, el) => { const triggerEl = $(el); const dropdownEl = triggerEl.parent().find('.dropdown-menu'); + const listEl = dropdownEl.find('[component="notifications/list"]'); if (dropdownEl.hasClass('show')) { app.require('notifications').then((notifications) => { - notifications.loadNotifications(triggerEl, dropdownEl.find('[component="notifications/list"]')); + notifications.loadNotifications(triggerEl, listEl); }); } + + dropdownEl.on('click', '[data-filter]', (e) => { + const filter = e.target.getAttribute('data-filter'); + dropdownEl.find('[data-filter]').removeClass('active'); + e.target.classList.add('active'); + if (filter === 'unread') { + listEl.get(0).querySelectorAll('[data-nid]:not(.unread)').forEach((e) => { + e.classList.toggle('hidden', true); + }); + } else { + listEl.get(0).querySelectorAll('[data-nid]').forEach((e) => { + e.classList.toggle('hidden', false); + }); + } + const visibleNotifCount = dropdownEl.find('[data-nid]:not(.hidden)').length; + dropdownEl.find('.no-notifs').toggleClass('hidden', visibleNotifCount !== 0); + }); }); socket.removeListener('event:new_notification', onNewNotification); diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js index 49a0e23be0..7160a1ed51 100644 --- a/public/src/client/topic/postTools.js +++ b/public/src/client/topic/postTools.js @@ -287,7 +287,9 @@ define('forum/topic/postTools', [ showStaleWarning(function () { let username = getUserSlug(button); - if (getData(button, 'data-uid') === '0' || !getData(button, 'data-userslug')) { + const postUid = getData(button, 'data-uid'); + const isSelfPost = postUid === String(app.user.uid); + if (isSelfPost || postUid === '0' || !getData(button, 'data-userslug')) { username = ''; } @@ -322,22 +324,17 @@ define('forum/topic/postTools', [ const username = getUserSlug(button); const toPid = getData(button, 'data-pid'); - function quote(text) { - hooks.fire('action:composer.addQuote', { - tid: tid, - pid: toPid, - username: username, - title: ajaxify.data.titleRaw, - text: text, - }); - } + const body = selectedNode.text && toPid && toPid === selectedNode.pid ? + selectedNode.text : + (await api.get(`/posts/${encodeURIComponent(toPid)}/raw`)).content; - if (selectedNode.text && toPid && toPid === selectedNode.pid) { - return quote(selectedNode.text); - } - - const { content } = await api.get(`/posts/${encodeURIComponent(toPid)}/raw`); - quote(content); + hooks.fire('action:composer.addQuote', { + tid: tid, + pid: toPid, + username: username, + title: ajaxify.data.titleRaw, + body: body, + }); }); } diff --git a/public/src/client/world.js b/public/src/client/world.js index 1318195060..ec2c4ef497 100644 --- a/public/src/client/world.js +++ b/public/src/client/world.js @@ -3,10 +3,10 @@ define('forum/world', [ 'forum/infinitescroll', 'search', 'sort', 'hooks', 'alerts', 'api', 'bootbox', 'helpers', 'forum/category/tools', - 'translator', 'quickreply', + 'translator', 'quickreply', 'handleBack', 'imagesloaded', ], function (infinitescroll, search, sort, hooks, alerts, api, bootbox, helpers, categoryTools, - translator, quickreply) { + translator, quickreply, handleBack, imagesLoaded) { const World = {}; World.init = function () { @@ -14,7 +14,7 @@ define('forum/world', [ quickreply.init({ route: '/topics', body: { - cid: ajaxify.data.cid, + cid: config.activitypub.worldDefaultCid || ajaxify.data.cid, }, }); @@ -22,6 +22,7 @@ define('forum/world', [ handleImages(); handleButtons(); handleHelp(); + handleShowMoreButtons(); categoryTools.init($('#world-feed')); socket.on('event:new_post', onNewPost); @@ -35,17 +36,45 @@ define('forum/world', [ const sortOptionsEl = document.getElementById('sort-options'); if (sortLabelEl && sortOptionsEl) { const params = new URLSearchParams(window.location.search); - if (params.get('sort') === 'popular') { - translator.translate(`[[world:popular-${params.get('term')}]]`, function (translated) { - sortLabelEl.innerText = translated; - }); - } else { - translator.translate('[[world:latest]]', function (translated) { - sortLabelEl.innerText = translated; - }); + switch(params.get('sort')) { + case 'popular': { + translator.translate(`[[world:popular-${params.get('term')}]]`, function (translated) { + sortLabelEl.innerText = translated; + }); + break; + } + + default: { + let suffix = ''; + if (params.get('all') === '1') { + suffix = '-all'; + } else if (params.get('local') === '1') { + suffix = '-local'; + } + translator.translate(`[[world:latest${suffix}]]`, function (translated) { + sortLabelEl.innerText = translated; + }); + break; + } } } + handleBack.init((after, handleBackCb) => { + loadTopicsAfter(after, undefined, 1, (payload, callback) => { + app.parseAndTranslate(ajaxify.data.template.name, 'posts', payload, function (html) { + const listEl = document.getElementById('world-feed'); + $(listEl).append(html); + imagesLoaded(listEl, () => { + html.find('.timeago').timeago(); + handleImages(); + handleShowMoreButtons(); + callback(); + handleBackCb(); + }); + }); + }); + }, { container: '#world-feed' }); + search.enableQuickSearch({ searchElements: { inputEl: $('[component="category-search"]'), @@ -64,18 +93,24 @@ define('forum/world', [ if (!config.usePagination) { infinitescroll.init((direction) => { const posts = Array.from(document.querySelectorAll('[component="category/topic"]')); - const afterEl = direction > 0 ? posts.pop() : posts.shift(); - const after = (parseInt(afterEl.getAttribute('data-index'), 10) || 0) + (direction > 0 ? 1 : 0); - if (after < config.topicsPerPage) { + if (!posts.length) { return; } - loadTopicsAfter(after, direction, (payload, callback) => { + const afterEl = direction > 0 ? posts.pop() : posts.shift(); + const index = (parseInt(afterEl.getAttribute('data-index'), 10) || 0) + (direction > 0 ? 1 : 0); + const after = afterEl.getAttribute('data-tid'); + if (index < config.topicsPerPage) { + return; + } + + loadTopicsAfter(index, after, direction, (payload, callback) => { app.parseAndTranslate(ajaxify.data.template.name, 'posts', payload, function (html) { const listEl = document.getElementById('world-feed'); - $(listEl).append(html); + $(listEl)[direction === -1 ? 'prepend' : 'append'](html); html.find('.timeago').timeago(); handleImages(); + handleShowMoreButtons(); callback(); }); }); @@ -94,10 +129,11 @@ define('forum/world', [ return Math.floor(after / config.topicsPerPage) + (direction > 0 ? 1 : 0); } - function loadTopicsAfter(after, direction, callback) { + function loadTopicsAfter(index, after, direction, callback) { callback = callback || function () {}; const query = utils.params(); - query.page = calculateNextPage(after, direction); + query.page = calculateNextPage(index, direction); + query.after = after; infinitescroll.loadMoreXhr(query, callback); } @@ -208,6 +244,41 @@ define('forum/world', [ $('[component="post/content"] img:not(.not-responsive)').addClass('img-fluid'); } + function handleShowMoreButtons() { + const feedEl = document.getElementById('world-feed'); + if (!feedEl) { + return; + } + + feedEl.querySelectorAll('[component="post/content"]').forEach((el) => { + const initted = el.getAttribute('data-showmore'); + if (parseInt(initted, 10) === 1) { + return; + } + + if (el.clientHeight < el.scrollHeight - 1) { + el.parentNode.querySelector('[component="show/more"]').classList.remove('hidden'); + el.classList.toggle('clamp-fade-6', true); + } + el.setAttribute('data-showmore', '1'); + }); + + if (parseInt(feedEl.getAttribute('data-showmore'), 10) !== 1) { + feedEl.addEventListener('click', (e) => { + const subselector = e.target.closest('[component="show/more"]'); + if (subselector) { + const postContent = subselector.closest('.post-body').querySelector('[component="post/content"]'); + const isShowingMore = parseInt(subselector.getAttribute('ismore'), 10) === 1; + postContent.classList.toggle('line-clamp-6', isShowingMore); + postContent.classList.toggle('clamp-fade-6', isShowingMore); + $(subselector).translateText(isShowingMore ? '[[world:see-more]]' : '[[world:see-less]]'); + subselector.setAttribute('ismore', isShowingMore ? 0 : 1); + } + }); + feedEl.setAttribute('data-showmore', '1'); + } + } + function updateDropdowns(modified_cids, state) { modified_cids.forEach(function (cid) { const category = $('[data-cid="' + cid + '"]'); @@ -234,6 +305,7 @@ define('forum/world', [ feedEl.prepend(...html); handleImages(); + handleShowMoreButtons(); } return World; diff --git a/public/src/modules/accounts/invite.js b/public/src/modules/accounts/invite.js index 0f121a37cc..ed83914765 100644 --- a/public/src/modules/accounts/invite.js +++ b/public/src/modules/accounts/invite.js @@ -19,7 +19,7 @@ define('accounts/invite', ['api', 'benchpress', 'bootbox', 'alerts'], function ( buttons: { cancel: { label: `[[${isACP() ? 'admin/manage/users:alerts.button-cancel' : 'modules:bootbox.cancel'}]]`, - className: 'btn-default', + className: 'btn-light', }, invite: { label: `[[${isACP() ? 'admin/manage/users:invite' : 'users:invite'}]]`, diff --git a/public/src/modules/accounts/picture.js b/public/src/modules/accounts/picture.js index 0bec1a24a9..7ddd4cebb7 100644 --- a/public/src/modules/accounts/picture.js +++ b/public/src/modules/accounts/picture.js @@ -27,7 +27,12 @@ define('accounts/picture', [ icon: { text: ajaxify.data['icon:text'], bgColor: ajaxify.data['icon:bgColor'] }, defaultAvatar: ajaxify.data.defaultAvatar, allowProfileImageUploads: ajaxify.data.allowProfileImageUploads, - iconBackgrounds: ajaxify.data.iconBackgrounds, + iconBackgrounds: ajaxify.data.iconBackgrounds.map((color) => { + return { + color, + selected: color === ajaxify.data['icon:bgColor'], + }; + }), user: { uid: ajaxify.data.uid, username: ajaxify.data.username, @@ -55,9 +60,8 @@ define('accounts/picture', [ }, }); - modal.on('shown.bs.modal', updateImages); - modal.on('click', '.list-group-item', function selectImageType() { - modal.find('.list-group-item').removeClass('active'); + modal.on('click', '[component="profile/picture/button"]', function selectImageType() { + modal.find('[component="profile/picture/button"]').removeClass('active'); $(this).addClass('active'); }); @@ -69,34 +73,17 @@ define('accounts/picture', [ handleImageUpload(modal); - function updateImages() { - // Check to see which one is the active picture - if (!ajaxify.data.picture) { - modal.find('[data-type="default"]').addClass('active'); - } else { - modal.find('.list-group-item img').each(function () { - if (this.getAttribute('src') === ajaxify.data.picture) { - $(this).parents('.list-group-item').addClass('active'); - } - }); - } - - // Update avatar background colour - const iconbgEl = modal.find(`[data-bg-color="${ajaxify.data['icon:bgColor']}"]`); - if (iconbgEl.length) { - iconbgEl.addClass('selected'); - } else { - modal.find('[data-bg-color="transparent"]').addClass('selected'); - } - } - function saveSelection() { - const type = modal.find('.list-group-item.active').attr('data-type'); + const activeBtn = modal.find('[component="profile/picture/button"].active'); + const type = activeBtn.attr('data-type'); + const picture = activeBtn.find('img').attr('src'); const iconBgColor = modal.find('[data-bg-color].selected').attr('data-bg-color') || 'transparent'; - changeUserPicture(type, iconBgColor).then(() => { + api.put(`/users/${ajaxify.data.theirid}/picture`, { + type, picture, iconBgColor, + }).then(() => { Picture.updateHeader( - type === 'default' ? '' : modal.find('.list-group-item.active img').attr('src'), + type === 'default' ? '' : picture, iconBgColor ); ajaxify.refresh(); @@ -121,7 +108,9 @@ define('accounts/picture', [ const headerIconEl = $(`[component="header/avatar"] [component="avatar/icon"]`); if (picture) { - if (!headerPictureEl.length && headerIconEl.length) { + if (headerPictureEl.length) { + headerPictureEl.attr('src', picture); + } else if (headerIconEl.length) { const img = $(''); $(headerIconEl[0].attributes).each(function () { img.attr(this.nodeName, this.nodeValue); @@ -158,13 +147,6 @@ define('accounts/picture', [ } } - function onRemoveComplete() { - if (ajaxify.data.uploadedpicture === ajaxify.data.picture) { - ajaxify.refresh(); - Picture.updateHeader(); - } - } - modal.find('[data-action="upload"]').on('click', function () { modal.modal('hide'); @@ -217,21 +199,24 @@ define('accounts/picture', [ }); modal.find('[data-action="remove-uploaded"]').on('click', function () { + const removeBtn = $(this); + const removePicture = removeBtn.attr('data-url'); socket.emit('user.removeUploadedPicture', { uid: ajaxify.data.theirid, + picture: removePicture, }, function (err) { - modal.modal('hide'); if (err) { return alerts.error(err); } - onRemoveComplete(); + removeBtn.parent().remove(); + if (removePicture === ajaxify.data.picture) { + modal.modal('hide'); + ajaxify.refresh(); + Picture.updateHeader(); + } }); }); } - function changeUserPicture(type, bgColor) { - return api.put(`/users/${ajaxify.data.theirid}/picture`, { type, bgColor }); - } - return Picture; }); diff --git a/public/src/modules/handleBack.js b/public/src/modules/handleBack.js index 2df8baceda..97fcc0422f 100644 --- a/public/src/modules/handleBack.js +++ b/public/src/modules/handleBack.js @@ -8,9 +8,17 @@ define('handleBack', [ ], function (components, storage, navigator, pagination) { const handleBack = {}; let loadTopicsMethod; + const elements = new Map(); + const defaults = new Map([ + ['container', '[component="category"]'], + ]); - handleBack.init = function (_loadTopicsMethod) { + handleBack.init = function (_loadTopicsMethod, _elements = {}) { loadTopicsMethod = _loadTopicsMethod; + ['container'].forEach((prop) => { + elements.set(prop, _elements[prop] || defaults.get(prop)); + }); + saveClickedIndex(); $(window).off('action:popstate', onBackClicked).on('action:popstate', onBackClicked); }; @@ -18,10 +26,10 @@ define('handleBack', [ handleBack.onBackClicked = onBackClicked; function saveClickedIndex() { - $('[component="category"]').on('click', '[component="topic/header"]', function () { - const clickedIndex = $(this).parents('[data-index]').attr('data-index'); + $(elements.get('container')).on('click', '[data-index]', function () { + const clickedIndex = $(this).attr('data-index'); const windowScrollTop = $(window).scrollTop(); - $('[component="category/topic"]').each(function (index, el) { + $(elements.get('container')).find('[data-index]').each(function (index, el) { if ($(el).offset().top - windowScrollTop > 0) { storage.setItem('category:bookmark', $(el).attr('data-index')); storage.setItem('category:bookmark:clicked', clickedIndex); @@ -38,6 +46,7 @@ define('handleBack', [ ajaxify.data.template.category || ajaxify.data.template.recent || ajaxify.data.template.popular || + ajaxify.data.template.world || highlightUnread ) { let bookmarkIndex = storage.getItem('category:bookmark'); @@ -67,7 +76,7 @@ define('handleBack', [ return; } - $('[component="category"]').empty(); + $(elements.get('container')).empty(); loadTopicsMethod(Math.max(0, bookmarkIndex - 1) + 1, function () { handleBack.scrollToTopic(bookmarkIndex, clickedIndex); }); diff --git a/public/src/modules/iconSelect.js b/public/src/modules/iconSelect.js index 409ddb059b..712d3e8e12 100644 --- a/public/src/modules/iconSelect.js +++ b/public/src/modules/iconSelect.js @@ -252,7 +252,7 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) { buttons: { noIcon: { label: 'No Icon', - className: 'btn-default', + className: 'btn-light', callback: function () { el.removeClass(selected.icon); for (const style of selected.styles) { diff --git a/public/src/modules/notifications.js b/public/src/modules/notifications.js index f4806eafdf..1e68cb724a 100644 --- a/public/src/modules/notifications.js +++ b/public/src/modules/notifications.js @@ -42,16 +42,15 @@ define('notifications', [ hooks.fire('filter:notifications.load', { notifications: notifs }).then(({ notifications }) => { app.parseAndTranslate('partials/notifications_list', { notifications }, function (html) { notifList.html(html); - notifList.off('click').on('click', '[data-nid]', function (ev) { - const notifEl = $(this); + notifList.off('click').on('click', '[component="notifications/item/link"]', function (ev) { + const notifEl = $(this).parents('[data-nid]'); if (scrollToPostIndexIfOnPage(notifEl)) { ev.stopPropagation(); ev.preventDefault(); - if (triggerEl) { - triggerEl.dropdown('toggle'); - } } + triggerEl?.dropdown('toggle'); + const unread = notifEl.hasClass('unread'); if (!unread) { return; @@ -61,6 +60,10 @@ define('notifications', [ }); components.get('notifications').on('click', '.mark-all-read', () => { Notifications.markAllRead(); + triggerEl?.dropdown('toggle'); + }); + components.get('notifications').on('click', `[href="${config.relative_path}/notifications"]`, () => { + triggerEl?.dropdown('toggle'); }); Notifications.handleUnreadButton(notifList); @@ -86,7 +89,6 @@ define('notifications', [ $this.find('.unread').toggleClass('hidden', unread); $this.find('.read').toggleClass('hidden', !unread); }); - return false; }); }; diff --git a/public/src/modules/quickreply.js b/public/src/modules/quickreply.js index 9172ca3769..3a9573fb7b 100644 --- a/public/src/modules/quickreply.js +++ b/public/src/modules/quickreply.js @@ -3,9 +3,11 @@ define('quickreply', [ 'components', 'autocomplete', 'api', 'alerts', 'uploadHelpers', 'mousetrap', 'storage', 'hooks', + 'categorySelector', ], function ( components, autocomplete, api, - alerts, uploadHelpers, mousetrap, storage, hooks + alerts, uploadHelpers, mousetrap, storage, hooks, + categorySelector, ) { const QuickReply = { _autocomplete: null, @@ -17,6 +19,18 @@ define('quickreply', [ return; } + if (opts?.body?.cid && $('[component="topic/quickreply/container"] [component="category-selector"]')) { + categorySelector.init($('[component="category-selector"]'), { + privilege: 'topics:create', + selectedCategory: ajaxify.data.selectedCategory, + onSelect: function (category) { + opts.body = opts.body || {}; + opts.body.cid = category.cid; + }, + }); + $('[component="topic/quickreply/container"] [component="topic/quickreply/category-selector"').removeClass('hidden'); + } + const qrDraftId = ajaxify.data.tid ? `qr:draft:tid:${ajaxify.data.tid}` : `qr:draft:cid:${opts?.body?.cid || -1}`; const data = { element: element, diff --git a/public/src/modules/topicSelect.js b/public/src/modules/topicSelect.js index 50d38c4ba7..70a53f25a0 100644 --- a/public/src/modules/topicSelect.js +++ b/public/src/modules/topicSelect.js @@ -7,13 +7,14 @@ define('topicSelect', ['components'], function (components) { let topicsContainer; - TopicSelect.init = function (onSelect, containerEl) { + TopicSelect.init = function (onSelect, onLongPress, containerEl) { topicsContainer = containerEl || $('[component="category"]'); topicsContainer.on('selectstart', '[component="topic/select"]', function (ev) { ev.preventDefault(); }); - topicsContainer.on('click', '[component="topic/select"]', function (ev) { + let isLongPress = false; + const click = function (ev) { const select = $(this); const topicEl = select.parents('[component="category/topic"]'); if (ev.shiftKey) { @@ -28,6 +29,44 @@ define('topicSelect', ['components'], function (components) { if (typeof onSelect === 'function') { onSelect(); } + }; + topicsContainer.on('click', '[component="topic/select"]', function (ev) { + if (isLongPress) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + return false; + } + + click.call(this, ev); + }); + + // Long press + let longPressTimeout; + const start = function (ev) { + isLongPress = false; + longPressTimeout = setTimeout(() => { + isLongPress = true; + click.call(this, ev); + if (navigator.vibrate) { + navigator.vibrate(50); + } + const topicEl = this.closest('[component="category/topic"]'); + if (topicEl.classList.contains('selected')) { + onLongPress(); + } + }, 500); + }; + const cancel = () => { + clearTimeout(longPressTimeout); + }; + topicsContainer.on('mousedown', '[component="topic/select"]', start); + topicsContainer.on('touchstart', '[component="topic/select"]', start); + topicsContainer.on('mouseup', '[component="topic/select"]', cancel); + topicsContainer.on('mouseleave', '[component="topic/select"]', cancel); + topicsContainer.on('touchend', '[component="topic/select"]', cancel); + topicsContainer.on('touchcancel', '[component="topic/select"]', cancel); + topicsContainer.on('contextmenu', '[component="topic/select"]', (e) => { + e.preventDefault(); }); }; diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index 90fadfe628..6c28b30e03 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -602,7 +602,6 @@ Actors.prune = async () => { let deletionCountNonExisting = 0; let notDeletedDueToLocalContent = 0; const preservedIds = []; - const cleanupUids = []; await batch.processArray(ids, async (ids) => { const exists = await Promise.all([ @@ -652,7 +651,7 @@ Actors.prune = async () => { } catch (err) { winston.error(`Failed to delete user with uid ${uid}: ${err.stack}`); if (err.message === '[[error:no-user]]') { - cleanupUids.push(uid); + missing.add(uid); } } } else { @@ -661,14 +660,6 @@ Actors.prune = async () => { } })); - if (cleanupUids.length) { - await Promise.all([ - db.sortedSetRemove('usersRemote:lastCrawled', cleanupUids), - db.deleteAll(cleanupUids.map(uid => `userRemote:${uid}`)), - ]); - winston.info(`[actors/prune] Cleaned up ${cleanupUids.length} remote users that were not found in the database.`); - } - // Remote categories let counts = await categories.getCategoriesFields(cids, ['topic_count']); counts = counts.map(count => count.topic_count); @@ -688,13 +679,17 @@ Actors.prune = async () => { })); deletionCountNonExisting += missing.size; - await db.sortedSetRemove('usersRemote:lastCrawled', Array.from(missing)); + if (missing.size) { + await db.sortedSetRemove('usersRemote:lastCrawled', Array.from(missing)); + winston.info(`[actors/prune] Cleaned up ${missing.size} remote users that were not found in the database.`); + } + // update timestamp in usersRemote:lastCrawled so we don't try to delete users // with content over and over const now = Date.now(); await db.sortedSetAdd('usersRemote:lastCrawled', preservedIds.map(() => now), preservedIds); }, { - batch: 50, + batch: 10, interval: 1000, }); diff --git a/src/activitypub/contexts.js b/src/activitypub/contexts.js index 8335ae7cc4..fa4709158a 100644 --- a/src/activitypub/contexts.js +++ b/src/activitypub/contexts.js @@ -25,7 +25,7 @@ Contexts.get = async (uid, id) => { } try { - ({ id, type, context } = await activitypub.get('uid', uid, id, { headers })); + ({ id, type, context } = await activitypub.get('uid', uid, id, { headers, cache: false })); if (activitypub._constants.acceptable.contextTypes.has(type)) { // is context activitypub.helpers.log(`[activitypub/context] ${id} is the context.`); return { context: id }; @@ -35,7 +35,7 @@ Contexts.get = async (uid, id) => { } // context provided; try to resolve it. - ({ type } = await activitypub.get('uid', uid, context)); + ({ type } = await activitypub.get('uid', uid, context, { cache: false })); } catch (e) { if (e.code === 'ap_get_304') { activitypub.helpers.log(`[activitypub/context] ${id} context unchanged.`); @@ -65,7 +65,7 @@ Contexts.getItems = async (uid, id, options) => { } else { activitypub.helpers.log(`[activitypub/context] Retrieving context/page ${id}`); try { - object = await activitypub.get('uid', uid, id); + object = await activitypub.get('uid', uid, id, { cache: false }); } catch (e) { return false; } diff --git a/src/activitypub/helpers.js b/src/activitypub/helpers.js index 044fc2c82d..3b6e7549aa 100644 --- a/src/activitypub/helpers.js +++ b/src/activitypub/helpers.js @@ -44,9 +44,9 @@ Helpers.log = (message) => { if (!message) { return _lastLog; } - _lastLog = message; if (process.env.NODE_ENV === 'development') { + winston.verbose(message); } }; @@ -473,7 +473,7 @@ Helpers.generateCollection = async ({ set, method, count, page, perPage, url }) } else if (set) { method = method.bind(null, set); } - count = count || await db.sortedSetCard(set); + count = count ?? await db.sortedSetCard(set); const pageCount = Math.max(1, Math.ceil(count / perPage)); let items = []; let paginate = true; @@ -483,6 +483,7 @@ Helpers.generateCollection = async ({ set, method, count, page, perPage, url }) paginate = false; } + page = parseInt(page, 10) || undefined; if (page) { const invalidPagination = page < 1 || page > pageCount; if (invalidPagination) { diff --git a/src/activitypub/inbox.js b/src/activitypub/inbox.js index ea0e99de35..cd14579362 100644 --- a/src/activitypub/inbox.js +++ b/src/activitypub/inbox.js @@ -449,7 +449,7 @@ inbox.announce = async (req) => { if (!fromRelay && !cid && !syncedCids.length) { const { followers } = await activitypub.actors.getLocalFollowCounts(actor); if (!followers) { - winston.verbose(`[activitypub/inbox.announce] Rejecting ${object.id} via ${actor} due to no followers`); + activitypub.helpers.log(`[activitypub/inbox.announce] Rejecting ${object.id} via ${actor} due to no followers`); reject('Announce', object, actor); return; } @@ -517,11 +517,12 @@ inbox.follow = async (req) => { } const now = Date.now(); - await db.sortedSetAdd(`followersRemote:${id}`, now, actor); - await db.sortedSetAdd(`followingRemote:${actor}`, now, id); // for following backreference (actor pruning) - - const followerRemoteCount = await db.sortedSetCard(`followersRemote:${id}`); - await user.setUserField(id, 'followerRemoteCount', followerRemoteCount); + await Promise.all([ + db.sortedSetAdd(`followersRemote:${id}`, now, actor), + db.sortedSetAdd(`followingRemote:${actor}`, now, id), // for following backreference (actor pruning) + user.syncFollowCounts(id, false, true), + user.syncFollowCounts(actor, true, false), + ]); activitypub.actors._followerCache.del(id); await user.onFollow(actor, id); @@ -600,8 +601,8 @@ inbox.accept = async (req) => { db.sortedSetAdd(`followingRemote:${id}`, timestamp, actor), db.sortedSetAdd(`followersRemote:${actor}`, timestamp, id), // for followers backreference and notes assertion checking ]); - const followingRemoteCount = await db.sortedSetCard(`followingRemote:${id}`); - await user.setUserField(id, 'followingRemoteCount', followingRemoteCount); + await user.syncFollowCounts(id, true, false); + await user.syncFollowCounts(actor, false, true); } else if (localType === 'category') { if (!await db.isSortedSetMember(`followRequests:cid.${id}`, actor)) { if (await db.isSortedSetMember(`cid:${id}:following`, actor)) return; // already following @@ -635,7 +636,7 @@ inbox.undo = async (req) => { let { type: localType, id } = await helpers.resolveLocalId(object.object); - winston.verbose(`[activitypub/inbox/undo] ${type} ${localType && id ? `${localType} ${id}` : object.object} via ${actor}`); + activitypub.helpers.log(`[activitypub/inbox/undo] ${type} ${localType && id ? `${localType} ${id}` : object.object} via ${actor}`); switch (type) { case 'Follow': { @@ -649,9 +650,9 @@ inbox.undo = async (req) => { await Promise.all([ db.sortedSetRemove(`followersRemote:${id}`, actor), db.sortedSetRemove(`followingRemote:${actor}`, id), + user.syncFollowCounts(id, false, true), + user.syncFollowCounts(actor, true, false), ]); - const followerRemoteCount = await db.sortedSetCard(`followerRemote:${id}`); - await user.setUserField(id, 'followerRemoteCount', followerRemoteCount); notifications.rescind(`follow:${id}:uid:${actor}`); activitypub.actors._followerCache.del(id); break; @@ -680,7 +681,7 @@ inbox.undo = async (req) => { const allowed = await privileges.posts.can('posts:upvote', id, activitypub._constants.uid); if (!allowed) { - winston.verbose(`[activitypub/inbox.like] ${id} not allowed to be upvoted.`); + activitypub.helpers.log(`[activitypub/inbox.like] ${id} not allowed to be upvoted.`); reject('Like', object, actor); break; } diff --git a/src/activitypub/index.js b/src/activitypub/index.js index c5b5417020..37750664fe 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -229,7 +229,7 @@ ActivityPub.sign = async ({ key, keyId }, url, payload) => { // Construct signature header return { date, - digest, + ...(digest && { digest }), signature: `keyId="${keyId}",headers="${headers}",signature="${signature}",algorithm="hs2019"`, }; }; @@ -338,9 +338,9 @@ ActivityPub.get = async (type, id, uri, options) => { }); if (!String(response.statusCode).startsWith('2')) { - winston.verbose(`[activitypub/get] Received ${response.statusCode} when querying ${uri}`); + ActivityPub.helpers.log(`[activitypub/get] Received ${response.statusCode} when querying ${uri}`); if (body.hasOwnProperty('error')) { - winston.verbose(`[activitypub/get] Error received: ${body.error}`); + ActivityPub.helpers.log(`[activitypub/get] Error received: ${body.error}`); } const e = new Error(`[[error:activitypub.get-failed]]`); @@ -504,7 +504,7 @@ ActivityPub.buildRecipients = async function (object, options) { // Remove local uris, public addresses, and any ids that aren't asserted actors targets.forEach((address) => { - if (address.startsWith(nconf.get('url'))) { + if (utils.isNumber(address) || address.startsWith(nconf.get('url'))) { targets.delete(address); } }); diff --git a/src/activitypub/jobs.js b/src/activitypub/jobs.js index 57c2e51221..ca403a8045 100644 --- a/src/activitypub/jobs.js +++ b/src/activitypub/jobs.js @@ -1,46 +1,55 @@ 'use strict'; -const winston = require('winston'); -const { CronJob } = require('cron'); - const db = require('../database'); const meta = require('../meta'); const topics = require('../topics'); const utils = require('../utils'); +const cron = require('../cron'); + const activitypub = module.parent.exports; const Jobs = module.exports; -Jobs.start = () => { +Jobs.start = async () => { activitypub.helpers.log('[activitypub/jobs] Registering jobs.'); async function tryCronJob(method) { - if (!meta.config.activitypubEnabled) { - return; - } - try { + if (meta.config.activitypubEnabled) { await method(); - } catch (err) { - winston.error(err.stack); } } - new CronJob('0 0 * * *', async () => { - await tryCronJob(async () => { - await activitypub.notes.prune(); - await db.sortedSetsRemoveRangeByScore(['activities:datetime'], '-inf', Date.now() - 604800000); - }); - }, null, true, null, null, false); // change last argument to true for debugging - new CronJob('*/30 * * * *', async () => { - await tryCronJob(activitypub.actors.prune); - }, null, true, null, null, false); // change last argument to true for debugging + await cron.addJob({ + name: 'ap:notes:prune', + cronTime: '0 0 * * *', + runOnInit: false, + onTick: async () => { + await tryCronJob(async () => { + await activitypub.notes.prune(); + await db.sortedSetsRemoveRangeByScore(['activities:datetime'], '-inf', Date.now() - 604800000); + }); + }, + }); - new CronJob('0 * * * * *', async () => { - await tryCronJob(retryFailedMessages); - }, null, true, null, null, false); // change last argument to true for debugging + await cron.addJob({ + name: 'ap:actors:prune', + cronTime: '*/30 * * * *', + runOnInit: false, + onTick: async () => await tryCronJob(activitypub.actors.prune), + }); - new CronJob('15 * * * *', async () => { - await tryCronJob(backfill); - }, null, true, null, null, false); // change last argument to true for debugging + await cron.addJob({ + name: 'ap:retry:send', + cronTime: '0 * * * * *', + runOnInit: false, + onTick: async () => await tryCronJob(retryFailedMessages), + }); + + await cron.addJob({ + name: 'ap:backfill', + cronTime: '15 * * * *', + runOnInit: false, + onTick: async () => await tryCronJob(backfill), + }); }; async function retryFailedMessages() { diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js index 4e6fed1a80..030175fb36 100644 --- a/src/activitypub/mocks.js +++ b/src/activitypub/mocks.js @@ -743,18 +743,40 @@ Mocks.notes.public = async (post) => { } attachment = normalizeAttachment(attachment); + + // Retrieve alt text from content (if found) + if (source?.content && source?.mediaType === 'text/markdown') { + const mdImageRegex = /!\[(.+?)\]\(([^\\)]+)\)/g; + const found = new Map(); + let current = mdImageRegex.exec(source.content); + while (current !== null) { + const [, alt, src] = current; + found.set(src.replace('-resized', ''), alt); + current = mdImageRegex.exec(source.content); + } + + attachment = attachment.map((attachment) => { + if (found.has(attachment.url)) { + attachment.name = found.get(attachment.url); + } + + return attachment; + }); + } + + // 'image' seems to be used as the preview image in lemmy/piefed, use the first one. const image = attachment.filter(entry => entry.type === 'Image')?.shift(); - // let preview; + let preview; let summary = null; if (isArticle) { // Preview is not adopted by anybody, so is left commented-out for now - // preview = { - // type: 'Note', - // attributedTo: `${nconf.get('url')}/uid/${post.user.uid}`, - // content: post.content, - // published, - // attachment, - // }; + preview = { + type: 'Note', + attributedTo: `${nconf.get('url')}/uid/${post.user.uid}`, + content: post.content, + published, + attachment, + }; if (post.content.includes(meta.config.activitypubBreakString)) { const index = post.content.indexOf(meta.config.activitypubBreakString); @@ -793,10 +815,6 @@ Mocks.notes.public = async (post) => { let context = await posts.getPostField(post.pid, 'context'); context = context || `${nconf.get('url')}/topic/${post.topic.tid}`; - /** - * audience is exposed as part of 1b12 but is now ignored by Lemmy. - * Remove this and most references to audience in 2026. - */ let audience = utils.isNumber(post.category.cid) ? // default `${nconf.get('url')}/category/${post.category.cid}` : post.category.cid; if (inReplyTo) { @@ -807,6 +825,17 @@ Mocks.notes.public = async (post) => { } to.add(audience); + // Sneak in a mention for the remote category (so Mastodon users address distributor) + if (!audience.startsWith(nconf.get('url'))) { + const slug = await categories.getCategoryField(audience, 'slug'); + tag = tag || []; + tag.push({ + type: 'Mention', + href: audience, + name: `@${slug}`, + }); + } + let object = { '@context': 'https://www.w3.org/ns/activitystreams', id, @@ -822,7 +851,7 @@ Mocks.notes.public = async (post) => { context, audience, ...(summary && { summary }), - // preview, + preview, content: post.content, source, tag, @@ -957,6 +986,65 @@ Mocks.activities.create = async (pid, uid, post) => { return { activity, targets }; }; +Mocks.activities.like = async (pid, uid) => { + const authorUid = await posts.getPostField(pid, 'uid'); + + return { + id: `${nconf.get('url')}/uid/${uid}#activity/like/${encodeURIComponent(pid)}`, + type: 'Like', + actor: `${nconf.get('url')}/uid/${uid}`, + to: [activitypub._constants.publicAddress], + cc: [authorUid], + object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, + }; +}; + +Mocks.activities.dislike = async (pid, uid) => { + const authorUid = await posts.getPostField(pid, 'uid'); + + return { + id: `${nconf.get('url')}/uid/${uid}#activity/dislike/${encodeURIComponent(pid)}`, + type: 'Dislike', + actor: `${nconf.get('url')}/uid/${uid}`, + to: [activitypub._constants.publicAddress], + cc: [authorUid], + object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, + }; +}; + +Mocks.activities.announce = async (tid, uid) => { + const { mainPid: pid, cid } = await topics.getTopicFields(tid, ['mainPid', 'cid']); + const authorUid = await posts.getPostField(pid, 'uid'); // author + const { to, cc, targets } = await activitypub.buildRecipients({ + id: pid, + to: [activitypub._constants.publicAddress], + }, uid ? { uid } : { cid }); + if (!utils.isNumber(authorUid)) { + cc.push(authorUid); + targets.add(authorUid); + } + + const payload = uid ? { + id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/uid/${uid}`, + type: 'Announce', + actor: `${nconf.get('url')}/uid/${uid}`, + } : { + id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/cid/${cid}`, + type: 'Announce', + actor: `${nconf.get('url')}/category/${cid}`, + }; + + return { + activity: { + ...payload, + to, + cc, + object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, + }, + targets, + }; +}; + Mocks.tombstone = async properties => ({ '@context': 'https://www.w3.org/ns/activitystreams', type: 'Tombstone', diff --git a/src/activitypub/notes.js b/src/activitypub/notes.js index fa59c8450c..8522965826 100644 --- a/src/activitypub/notes.js +++ b/src/activitypub/notes.js @@ -218,6 +218,15 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => { post.toPid = urlMap.get(post.toPid); } + // Filter image attachments out if they are in content + const attachment = post?._activitypub?.attachment; + if (attachment && attachment.length) { + post._activitypub.attachment = attachment.filter((attachment) => { + const inContent = attachment.type === 'Image' && (post.sourceContent || post.content).includes(attachment.url); + return !inContent; + }); + } + return post; }).filter((p, idx) => !exists[idx]); const count = unprocessed.length; @@ -309,7 +318,7 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => { winston.warn(`[activitypub/notes.assert] Could not assert ${id} (${e.message}).`); return null; } finally { - winston.verbose(`[activitypub/notes.assert] Releasing lock (${id})`); + activitypub.helpers.log(`[activitypub/notes.assert] Releasing lock (${id})`); await db.deleteObjectField('locks', id); } }; @@ -554,7 +563,7 @@ Notes.getParentChain = async (uid, input) => { } } } catch (e) { - winston.verbose(`[activitypub/notes/getParentChain] Cannot retrieve ${id}, terminating here.`); + activitypub.helpers.log(`[activitypub/notes/getParentChain] Cannot retrieve ${id}, terminating here.`); } } }; @@ -778,7 +787,9 @@ async function pruneCidTids(cid, cuttoff) { max: cuttoff, batch: 500, }); - + if (!tidsWithNoEngagement.length) { + return; + } winston.info(`[notes/prune] ${tidsWithNoEngagement.length} topics eligible in cid:${cid} for pruning`); await batch.processArray(tidsWithNoEngagement, async (tids) => { diff --git a/src/activitypub/out.js b/src/activitypub/out.js index dbe3a3e8e4..5242e6df6d 100644 --- a/src/activitypub/out.js +++ b/src/activitypub/out.js @@ -254,12 +254,7 @@ Out.delete.note = enabledCheck(async (uid, pid) => { Out.like = {}; Out.like.note = enabledCheck(async (uid, pid) => { - const payload = { - id: `${nconf.get('url')}/uid/${uid}#activity/like/${encodeURIComponent(pid)}`, - type: 'Like', - actor: `${nconf.get('url')}/uid/${uid}`, - object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, - }; + const payload = await activitypub.mocks.activities.like(pid, uid); if (!activitypub.helpers.isUri(pid)) { // only 1b12 announce for local likes await activitypub.feps.announce(pid, payload); @@ -280,12 +275,7 @@ Out.like.note = enabledCheck(async (uid, pid) => { Out.dislike = {}; Out.dislike.note = enabledCheck(async (uid, pid) => { - const payload = { - id: `${nconf.get('url')}/uid/${uid}#activity/dislike/${encodeURIComponent(pid)}`, - type: 'Dislike', - actor: `${nconf.get('url')}/uid/${uid}`, - object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, - }; + const payload = activitypub.mocks.activities.dislike(pid, uid); if (!activitypub.helpers.isUri(pid)) { // only 1b12 announce for local likes await activitypub.feps.announce(pid, payload); @@ -320,37 +310,14 @@ Out.announce.topic = enabledCheck(async (tid, uid) => { } } - const authorUid = await posts.getPostField(pid, 'uid'); // author const allowed = await privileges.posts.can('topics:read', pid, activitypub._constants.uid); if (!allowed) { activitypub.helpers.log(`[activitypub/api] Not federating announce of pid ${pid} to the fediverse due to privileges.`); return; } - const { to, cc, targets } = await activitypub.buildRecipients({ - id: pid, - to: [activitypub._constants.publicAddress], - }, uid ? { uid } : { cid }); - if (!utils.isNumber(authorUid)) { - cc.push(authorUid); - targets.add(authorUid); - } - - const payload = uid ? { - id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/uid/${uid}`, - type: 'Announce', - actor: `${nconf.get('url')}/uid/${uid}`, - } : { - id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/cid/${cid}`, - type: 'Announce', - actor: `${nconf.get('url')}/category/${cid}`, - }; - await activitypub.send(uid ? 'uid' : 'cid', uid || cid, Array.from(targets), { - ...payload, - to, - cc, - object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, - }); + const { activity, targets } = await activitypub.mocks.activities.announce(tid, uid); + await activitypub.send(uid ? 'uid' : 'cid', uid || cid, Array.from(targets), activity); }); Out.flag = enabledCheck(async (uid, flag) => { @@ -504,7 +471,8 @@ Out.undo.follow = enabledCheck(async (type, id, actor) => { db.sortedSetRemove(`followingRemote:${id}`, actor), db.sortedSetRemove(`followRequests:uid.${id}`, actor), db.sortedSetRemove(`followersRemote:${actor}`, id), - db.decrObjectField(`user:${id}`, 'followingRemoteCount'), + user.syncFollowCounts(id, true, false), + user.syncFollowCounts(actor, false, true), ]); } else if (type === 'cid') { await Promise.all([ diff --git a/src/analytics.js b/src/analytics.js index 773f7088af..e054e2e733 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -1,6 +1,5 @@ 'use strict'; -const cronJob = require('cron').CronJob; const winston = require('winston'); const nconf = require('nconf'); const util = require('util'); @@ -12,6 +11,7 @@ const db = require('./database'); const utils = require('./utils'); const plugins = require('./plugins'); const pubsub = require('./pubsub'); +const cron = require('./cron'); const Analytics = module.exports; @@ -32,19 +32,28 @@ const runJobs = nconf.get('runJobs'); Analytics.pause = false; Analytics.init = async function () { - new cronJob('*/10 * * * * *', (async () => { - if (Analytics.pause) return; - publishLocalAnalytics(); - if (runJobs) { - await sleep(2000); - await Analytics.writeData(); - } - }), null, true); + await cron.addJob({ + name: 'analytics:publish', + cronTime: '*/10 * * * * *', + runOnAllNodes: true, + onTick: async () => { + if (Analytics.pause) return; + publishLocalAnalytics(); + if (runJobs) { + await sleep(2000); + await Analytics.writeData(); + } + }, + }); if (runJobs) { - new cronJob('*/30 * * * *', (async () => { - await db.sortedSetsRemoveRangeByScore(['ip:recent'], '-inf', Date.now() - 172800000); - }), null, true); + await cron.addJob({ + name: 'prune:ip:recent', + cronTime: '*/30 * * * *', + onTick: async () => { + await db.sortedSetsRemoveRangeByScore(['ip:recent'], '-inf', Date.now() - 172800000); + }, + }); } if (runJobs) { diff --git a/src/api/users.js b/src/api/users.js index 369a692cc0..b962968882 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -2,7 +2,7 @@ const path = require('path'); const fs = require('fs').promises; - +const nconf = require('nconf'); const validator = require('validator'); const winston = require('winston'); @@ -627,7 +627,14 @@ usersAPI.changePicture = async (caller, data) => { if (type === 'default') { picture = ''; } else if (type === 'uploaded') { - picture = await user.getUserField(data.uid, 'uploadedpicture'); + const cleanPath = data.picture.replace(new RegExp(`^${nconf.get('relative_path')}`), ''); + const isUserPicture = await user.isUserUploadedPicture(data.uid, cleanPath); + if (isUserPicture) { + await user.setUserField(data.uid, 'uploadedpicture', cleanPath); + picture = cleanPath; + } else { + picture = ''; + } } else if (type === 'external' && url) { picture = validator.escape(url); } else { diff --git a/src/categories/delete.js b/src/categories/delete.js index 5f96e32676..3575107336 100644 --- a/src/categories/delete.js +++ b/src/categories/delete.js @@ -52,6 +52,7 @@ module.exports = function (Categories) { `cid:${cid}:uid:watch:state`, `cid:${cid}:children`, `cid:${cid}:tag:whitelist`, + `cid:${cid}:privilegeMask`, `${utils.isNumber(cid) ? 'category' : 'categoryRemote'}:${cid}`, ]); const privilegeList = await privileges.categories.getPrivilegeList(); diff --git a/src/categories/icon.js b/src/categories/icon.js index 7aa94ab802..8ce4da9253 100644 --- a/src/categories/icon.js +++ b/src/categories/icon.js @@ -3,7 +3,6 @@ const path = require('path'); const fs = require('fs/promises'); const nconf = require('nconf'); -const winston = require('winston'); const { default: satori } = require('satori'); const sharp = require('sharp'); @@ -33,14 +32,12 @@ Icons.get = async (cid) => { }; Icons.flush = async (cid) => { - winston.verbose(`[categories/icons] Flushing ${cid}.`); const paths = Icons._constants.extensions.map(extension => path.resolve(nconf.get('upload_path'), 'category', `category-${cid}-icon.${extension}`)); await Promise.all(paths.map((async path => await fs.rm(path, { force: true })))); }; Icons.regenerate = async (cid) => { - winston.verbose(`[categories/icons] Regenerating ${cid}.`); const { icon, color, bgColor } = await categories.getCategoryData(cid); const fontPaths = new Map(Object.entries({ diff --git a/src/controllers/404.js b/src/controllers/404.js index bed1a085e3..1688b80a7a 100644 --- a/src/controllers/404.js +++ b/src/controllers/404.js @@ -9,12 +9,17 @@ const plugins = require('../plugins'); const activitypub = require('../activitypub'); const middleware = require('../middleware'); const helpers = require('../middleware/helpers'); -const { secureRandom } = require('../utils'); + +const relativePath = nconf.get('relative_path'); +const isClientScript = new RegExp(`^${relativePath}\\/assets\\/src\\/.+\\.js(\\?v=\\w+)?$`); + +const error404Icons = [ + 'fa-hippo', 'fa-cat', 'fa-otter', + 'fa-dog', 'fa-cow', 'fa-fish', + 'fa-dragon', 'fa-horse', 'fa-dove', +]; exports.handle404 = helpers.try(async (req, res) => { - const relativePath = nconf.get('relative_path'); - const isClientScript = new RegExp(`^${relativePath}\\/assets\\/src\\/.+\\.js(\\?v=\\w+)?$`); - if (plugins.hooks.hasListeners('action:meta.override404')) { return plugins.hooks.fire('action:meta.override404', { req: req, @@ -62,16 +67,11 @@ exports.send404 = helpers.try(async (req, res) => { bodyClass: helpers.buildBodyClass(req, res), }); } - const icons = [ - 'fa-hippo', 'fa-cat', 'fa-otter', - 'fa-dog', 'fa-cow', 'fa-fish', - 'fa-dragon', 'fa-horse', 'fa-dove', - ]; + await middleware.buildHeaderAsync(req, res); res.render('404', { path: validator.escape(path), title: '[[global:404.title]]', - bodyClass: helpers.buildBodyClass(req, res), - icon: icons[secureRandom(0, icons.length - 1)], + icon: error404Icons[Math.floor(Math.random() * error404Icons.length)], }); }); diff --git a/src/controllers/accounts/profile.js b/src/controllers/accounts/profile.js index fab317fe17..93be1d2b4e 100644 --- a/src/controllers/accounts/profile.js +++ b/src/controllers/accounts/profile.js @@ -24,6 +24,10 @@ profileController.get = async function (req, res, next) { return next(); } + if (!req.loggedIn && meta.config.activitypubEnabled && !res.locals.isAPI && !utils.isNumber(userData.uid)) { + return helpers.redirect(res, `/outgoing?url=${encodeURIComponent(userData.uid)}`); + } + await incrementProfileViews(req, userData); const [latestPosts, bestPosts, customUserFields] = await Promise.all([ diff --git a/src/controllers/activitypub/index.js b/src/controllers/activitypub/index.js index c64ef9ef57..b7eaa334c8 100644 --- a/src/controllers/activitypub/index.js +++ b/src/controllers/activitypub/index.js @@ -3,7 +3,9 @@ const nconf = require('nconf'); const winston = require('winston'); +const db = require('../../database'); const meta = require('../../meta'); +const posts = require('../../posts'); const user = require('../../user'); const activitypub = require('../../activitypub'); const utils = require('../../utils'); @@ -64,10 +66,8 @@ Controller.fetch = async (req, res, next) => { }; Controller.getFollowing = async (req, res) => { - const { followingCount, followingRemoteCount } = await user.getUserFields(req.params.uid, ['followingCount', 'followingRemoteCount']); - const totalItems = parseInt(followingCount || 0, 10) + parseInt(followingRemoteCount || 0, 10); - - const count = totalItems; + const followingCount = await user.getUserField(req.params.uid, 'followingCount'); + const count = parseInt(followingCount, 10); const collection = await activitypub.helpers.generateCollection({ method: user.getFollowing.bind(null, req.params.uid), count, @@ -90,10 +90,8 @@ Controller.getFollowing = async (req, res) => { }; Controller.getFollowers = async (req, res) => { - const { followerCount, followerRemoteCount } = await user.getUserFields(req.params.uid, ['followerCount', 'followerRemoteCount']); - const totalItems = parseInt(followerCount || 0, 10) + parseInt(followerRemoteCount || 0, 10); - - const count = totalItems; + const followerCount = await user.getUserField(req.params.uid, 'followerCount'); + const count = parseInt(followerCount, 10); const collection = await activitypub.helpers.generateCollection({ method: user.getFollowers.bind(null, req.params.uid), count, @@ -116,22 +114,138 @@ Controller.getFollowers = async (req, res) => { }; Controller.getOutbox = async (req, res) => { - // stub + // Posts, shares, and votes + const { uid } = req.params; + let { after, before } = req.query; + + let totalItems = await db.sortedSetsCard([`uid:${uid}:posts`, `uid:${uid}:upvote`, `uid:${uid}:downvote`, `uid:${uid}:shares`]); + totalItems = totalItems.reduce((sum, count) => { + sum += count; + return sum; + }, 0); + + const perPage = 20; + let paginate = true; + if (totalItems <= perPage) { + before = undefined; + after = undefined; + paginate = false; + } + + let prev; + let next; + const partOf = paginate && (after || before) && `${nconf.get('url')}/uid/${uid}/outbox`; + const first = paginate && !after && !before && `${nconf.get('url')}/uid/${uid}/outbox?after=${Date.now()}`; + const last = paginate && !after && !before && `${nconf.get('url')}/uid/${uid}/outbox?before=0`; + let activities; + + if (!paginate || after || before) { + const limit = after ? parseInt(after, 10) - 1 : parseInt(before, 10) + 1; + const method = after ? 'getSortedSetRevRangeByScoreWithScores' : 'getSortedSetRangeByScoreWithScores'; + + const [post, upvote, downvote, share] = await Promise.all([ + db[method](`uid:${uid}:posts`, 0, 20, limit, `${after ? '-' : '+'}inf`), + db[method](`uid:${uid}:upvote`, 0, 20, limit, `${after ? '-' : '+'}inf`), + db[method](`uid:${uid}:downvote`, 0, 20, limit, `${after ? '-' : '+'}inf`), + db[method](`uid:${uid}:shares`, 0, 20, limit, `${after ? '-' : '+'}inf`), + ]); + activities = [ + post.map(post => ({ ...post, type: 'post' })), + upvote.map(upvote => ({ ...upvote, type: 'upvote' })), + downvote.map(downvote => ({ ...downvote, type: 'downvote' })), + share.map(share => ({ ...share, type: 'share' })), + ].flat().sort((a, b) => b.score - a.score); + if (after) { + activities = activities.slice(0, 20); + } else { + activities = activities.slice(-20); + } + + if (activities.length) { + prev = `${nconf.get('url')}/uid/${uid}/outbox?before=${activities[0].score}`; + next = `${nconf.get('url')}/uid/${uid}/outbox?after=${activities[19].score}`; + + let postsData = activities.filter((({ type }) => type === 'post')); + postsData = await posts.getPostSummaryByPids(postsData.map(({ value }) => value), 0, { stripTags: false }); + postsData = postsData.reduce((map, postData) => { + map.set(postData.pid, postData); + return map; + }, new Map()); + + activities = await Promise.all(activities.map(async ({ type, value: id }) => { + switch (type) { + case 'post': { + const { activity } = await activitypub.mocks.activities.create(id, 0, postsData.get(id)); + return activity; + } + + case 'upvote': { + return activitypub.mocks.activities.like(id, uid); + } + + case 'downvote': { + return activitypub.mocks.activities.dislike(id, uid); + } + + case 'share': { + const { activity } = await activitypub.mocks.activities.announce(id, uid); + return activity; + } + } + })); + } + } + res.status(200).json({ '@context': 'https://www.w3.org/ns/activitystreams', - type: 'OrderedCollection', - totalItems: 0, - orderedItems: [], + id: `${nconf.get('url')}/uid/${uid}/outbox`, + type: paginate ? 'OrderedCollectionPage' : 'OrderedCollection', + totalItems, + ...(prev && { prev }), + ...(next && { next }), + ...(first && { first }), + ...(last && { last }), + ...(partOf && { partOf }), + orderedItems: activities, }); }; Controller.getCategoryOutbox = async (req, res) => { - // stub + const { cid } = req.params; + const { page } = req.query; + const set = `cid:${cid}:pids`; + const count = await db.sortedSetCard(set); + const collection = await activitypub.helpers.generateCollection({ + set, + count, + page, + perPage: 20, + url: `${nconf.get('url')}/category/${cid}/outbox`, + }); + if (collection.orderedItems) { + collection.orderedItems = await Promise.all(collection.orderedItems.map(async (pid) => { + let object; + if (utils.isNumber(pid)) { + const { activity } = await activitypub.mocks.activities.create(pid, 0); + object = activity; + } else { + object = pid; + } + + return { + id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/cid/${cid}`, + type: 'Announce', + actor: `${nconf.get('url')}/category/${cid}`, + to: [activitypub._constants.publicAddress], + cc: [`${nconf.get('url')}/category/${cid}/followers`], + object, + }; + })); + } + res.status(200).json({ '@context': 'https://www.w3.org/ns/activitystreams', - type: 'OrderedCollection', - totalItems: 0, - orderedItems: [], + ...collection, }); }; diff --git a/src/controllers/activitypub/topics.js b/src/controllers/activitypub/topics.js index 0e1fbe959a..26008e416c 100644 --- a/src/controllers/activitypub/topics.js +++ b/src/controllers/activitypub/topics.js @@ -16,14 +16,21 @@ const helpers = require('../helpers'); const controller = module.exports; controller.list = async function (req, res) { - const { topicsPerPage } = await user.getSettings(req.uid); - const page = parseInt(req.query.page, 10) || 1; - const start = Math.max(0, (page - 1) * topicsPerPage); - const stop = start + topicsPerPage - 1; + if (!req.uid && !req.query.sort && !req.query.local) { + return helpers.redirect(res, '/world?local=1', false); + } - const [userSettings, userPrivileges] = await Promise.all([ + const { topicsPerPage } = await user.getSettings(req.uid); + let { page, after } = req.query; + page = parseInt(page, 10) || 1; + let start = Math.max(0, (page - 1) * topicsPerPage); + let stop = start + topicsPerPage - 1; + + const [userSettings, userPrivileges, isAdminOrGlobalMod, selectedCategory] = await Promise.all([ user.getSettings(req.uid), privileges.categories.get('-1', req.uid), + user.isAdminOrGlobalMod(req.uid), + categories.getCategoryData(meta.config.activitypubWorldDefaultCid), ]); const targetUid = await user.getUidByUserslug(req.query.author); let cidQuery = { @@ -31,6 +38,7 @@ controller.list = async function (req, res) { cid: '-1', start: start, stop: stop, + after, sort: req.query.sort, settings: userSettings, query: req.query, @@ -41,22 +49,43 @@ controller.list = async function (req, res) { delete data.children; data.sort = req.query.sort; data.privileges = userPrivileges; + data.selectedCategory = selectedCategory; let tids; let topicCount; + let { local } = req.query; + local = parseInt(local, 10) === 1; if (req.query.sort === 'popular') { cidQuery = { ...cidQuery, - cids: ['-1'], sort: 'posts', term: req.query.term || 'day', + includeRemote: !local, + followingOnly: !req.query.all || !parseInt(req.query.all, 10), }; delete cidQuery.cid; ({ tids, topicCount } = await topics.getSortedTopics(cidQuery)); tids = tids.slice(start, stop !== -1 ? stop + 1 : undefined); } else { - tids = await categories.getTopicIds(cidQuery); - topicCount = await categories.getTopicCount(cidQuery); + cidQuery = { + ...cidQuery, + term: req.query.term, + includeRemote: !local, + followingOnly: !req.query.all || !parseInt(req.query.all, 10), + }; + delete cidQuery.cid; + ({ tids, topicCount } = await topics.getSortedTopics(cidQuery)); + + if (after) { + // Update start/stop with values inferred from `after` + const index = tids.indexOf(utils.isNumber(after) ? parseInt(after, 10) : after); + if (index && start - index < 1) { + const count = stop - start; + start = index + 1; + stop = start + count; + } + } + tids = tids.slice(start, stop !== -1 ? stop + 1 : undefined); } data.topicCount = topicCount; @@ -72,7 +101,7 @@ controller.list = async function (req, res) { posts.hasBookmarked(mainPids, req.uid), ]); - const thumbs = await topics.thumbs.load(topicData); + const thumbs = await topics.thumbs.load(topicData, { thumbsOnly: 1 }); const tidToThumbs = _.zipObject(uniqTids, thumbs); const teasers = await topics.getTeasers(postData.map(p => p.topic), { uid: req.uid }); postData.forEach((p, index) => { @@ -92,33 +121,37 @@ controller.list = async function (req, res) { }); data.showThumbs = req.loggedIn || meta.config.privateUploads !== 1; data.posts = postData; - data.showTopicTools = true; - data.showSelect = true; + data.showTopicTools = isAdminOrGlobalMod; + data.showSelect = isAdminOrGlobalMod; // Tracked/watched categories - let cids = await user.getCategoriesByStates(req.uid, [ - categories.watchStates.tracking, categories.watchStates.watching, - ]); - cids = cids.filter(cid => !utils.isNumber(cid)); - const [categoryData, watchState] = await Promise.all([ - categories.getCategories(cids), - categories.getWatchState(cids, req.uid), - ]); - data.categories = categories.getTree(categoryData, 0); - await Promise.all([ - categories.getRecentTopicReplies(categoryData, req.uid, req.query), - categories.setUnread(data.categories, cids, req.uid), - ]); - data.categories.forEach((category, idx) => { - if (category) { - helpers.trimChildren(category); - helpers.setCategoryTeaser(category); - category.isWatched = watchState[idx] === categories.watchStates.watching; - category.isTracked = watchState[idx] === categories.watchStates.tracking; - category.isNotWatched = watchState[idx] === categories.watchStates.notwatching; - category.isIgnored = watchState[idx] === categories.watchStates.ignoring; - } - }); + if (req.uid) { + let cids = await user.getCategoriesByStates(req.uid, [ + categories.watchStates.tracking, categories.watchStates.watching, + ]); + cids = cids.filter(cid => !utils.isNumber(cid)); + const [categoryData, watchState] = await Promise.all([ + categories.getCategories(cids), + categories.getWatchState(cids, req.uid), + ]); + data.categories = categories.getTree(categoryData, 0); + await Promise.all([ + categories.getRecentTopicReplies(categoryData, req.uid, req.query), + categories.setUnread(data.categories, cids, req.uid), + ]); + data.categories.forEach((category, idx) => { + if (category) { + helpers.trimChildren(category); + helpers.setCategoryTeaser(category); + category.isWatched = watchState[idx] === categories.watchStates.watching; + category.isTracked = watchState[idx] === categories.watchStates.tracking; + category.isNotWatched = watchState[idx] === categories.watchStates.notwatching; + category.isIgnored = watchState[idx] === categories.watchStates.ignoring; + } + }); + } else { + data.categories = []; + } data.title = translator.escape(data.name); data.breadcrumbs = helpers.buildBreadcrumbs([]); diff --git a/src/controllers/admin.js b/src/controllers/admin.js index bdb8ca6ba1..00988e3906 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -25,6 +25,7 @@ const adminController = { errors: require('./admin/errors'), database: require('./admin/database'), cache: require('./admin/cache'), + jobs: require('./admin/jobs'), plugins: require('./admin/plugins'), settings: require('./admin/settings'), logger: require('./admin/logger'), diff --git a/src/controllers/admin/appearance.js b/src/controllers/admin/appearance.js index a1384a4185..13fc2ea015 100644 --- a/src/controllers/admin/appearance.js +++ b/src/controllers/admin/appearance.js @@ -1,9 +1,12 @@ 'use strict'; +const meta = require('../../meta'); + const appearanceController = module.exports; -appearanceController.themes = function (req, res) { - res.render(`admin/appearance/themes`, {}); +appearanceController.themes = async function (req, res) { + const themes = await meta.themes.get(); + res.render(`admin/appearance/themes`, { themes }); }; appearanceController.skins = function (req, res) { diff --git a/src/controllers/admin/jobs.js b/src/controllers/admin/jobs.js new file mode 100644 index 0000000000..f59b8f45b0 --- /dev/null +++ b/src/controllers/admin/jobs.js @@ -0,0 +1,12 @@ +'use strict'; + +const jobsController = module.exports; + +const cron = require('../../cron'); + +jobsController.get = async function (req, res) { + const jobs = await cron.getJobs(); + + res.render('admin/advanced/jobs', { jobs }); +}; + diff --git a/src/controllers/admin/uploads.js b/src/controllers/admin/uploads.js index cd9463fce2..21be9c441b 100644 --- a/src/controllers/admin/uploads.js +++ b/src/controllers/admin/uploads.js @@ -198,7 +198,6 @@ uploadsController.uploadTouchIcon = async function (req, res, next) { } }; - uploadsController.uploadMaskableIcon = async function (req, res, next) { const uploadedFile = req.files[0]; const allowedTypes = ['image/png']; @@ -214,6 +213,21 @@ uploadsController.uploadMaskableIcon = async function (req, res, next) { } }; +uploadsController.uploadScreenshot = async function (req, res, next) { + const uploadedFile = req.files[0]; + const allowedTypes = ['image/png', 'image/jpeg']; + + await validateUpload(uploadedFile, allowedTypes); + try { + const imageObj = await file.saveFileToLocal('screenshot.png', 'system', uploadedFile.path); + res.json([{ name: uploadedFile.name, url: imageObj.url }]); + } catch (err) { + next(err); + } finally { + file.delete(uploadedFile.path); + } +}; + uploadsController.uploadFile = async function (req, res, next) { const uploadedFile = req.files[0]; let params; diff --git a/src/controllers/api.js b/src/controllers/api.js index 4fd83dcd5b..ba49ccb29c 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -103,6 +103,7 @@ apiController.loadConfig = async function (req) { }, activitypub: { probe: meta.config.activitypubEnabled && meta.config.activitypubProbe, + worldDefaultCid: meta.config.activitypubWorldDefaultCid, }, }; diff --git a/src/controllers/helpers.js b/src/controllers/helpers.js index 7101170357..3f635a4a80 100644 --- a/src/controllers/helpers.js +++ b/src/controllers/helpers.js @@ -423,6 +423,10 @@ helpers.getHomePageRoutes = async function (uid) { route: 'categories', name: 'Categories', }, + { + route: 'world', + name: 'World', + }, { route: 'unread', name: 'Unread', diff --git a/src/controllers/index.js b/src/controllers/index.js index 0336db8d1d..2e55cfe646 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -1,11 +1,14 @@ 'use strict'; +const path = require('path'); const nconf = require('nconf'); const validator = require('validator'); +const mime = require('mime'); const meta = require('../meta'); const user = require('../user'); const plugins = require('../plugins'); +const image = require('../image'); const privilegesHelpers = require('../privileges/helpers'); const helpers = require('./helpers'); @@ -271,6 +274,7 @@ Controllers.manifest = async function (req, res) { const manifest = { name: meta.config.title || 'NodeBB', short_name: meta.config['title:short'] || meta.config.title || 'NodeBB', + ...(meta.config.description && { description: meta.config.description }), start_url: nconf.get('url'), display: 'standalone', orientation: 'portrait', @@ -279,6 +283,33 @@ Controllers.manifest = async function (req, res) { icons: [], }; + if (meta.config['brand:screenshot']) { + let sizes; + try { + const { width, height } = await image.size(path.join(nconf.get('base_dir'), meta.config['brand:screenshot'].replace('assets', 'public'))); + sizes = `${width}x${height}`; + } catch (e) { + // noop + } + manifest.screenshots = [ + { + src: `${nconf.get('relative_path')}${meta.config['brand:screenshot']}`, + ...(sizes && { sizes }), + type: mime.getType(meta.config['brand:screenshot']), + }, + ]; + } else { + manifest.screenshots = [ + { + src: `${nconf.get('relative_path')}/assets/images/screenshot-default.png`, + sizes: '446x778', + type: 'image/png', + form_factor: 'narrow', + label: 'Default home page of a vanilla NodeBB installation.', + }, + ]; + } + if (meta.config['brand:touchIcon']) { manifest.icons.push({ src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-36.png`, @@ -316,6 +347,43 @@ Controllers.manifest = async function (req, res) { type: 'image/png', density: 10.0, }); + } else { + manifest.icons.push({ + src: `${nconf.get('relative_path')}/assets/images/touch/36.png`, + sizes: '36x36', + type: 'image/png', + density: 0.75, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/48.png`, + sizes: '48x48', + type: 'image/png', + density: 1.0, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/72.png`, + sizes: '72x72', + type: 'image/png', + density: 1.5, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/96.png`, + sizes: '96x96', + type: 'image/png', + density: 2.0, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/144.png`, + sizes: '144x144', + type: 'image/png', + density: 3.0, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/192.png`, + sizes: '192x192', + type: 'image/png', + density: 4.0, + }, { + src: `${nconf.get('relative_path')}/assets/images/touch/512.png`, + sizes: '512x512', + type: 'image/png', + density: 10.0, + }); } diff --git a/src/controllers/posts.js b/src/controllers/posts.js index 44f2b06649..cfda2c90bb 100644 --- a/src/controllers/posts.js +++ b/src/controllers/posts.js @@ -6,7 +6,7 @@ const querystring = require('querystring'); const meta = require('../meta'); const posts = require('../posts'); const privileges = require('../privileges'); -const activitypub = require('../activitypub'); +// const activitypub = require('../activitypub'); const utils = require('../utils'); const helpers = require('./helpers'); @@ -19,12 +19,16 @@ postsController.redirectToPost = async function (req, res, next) { return next(); } - // Kickstart note assertion if applicable - if (!utils.isNumber(pid) && req.uid && meta.config.activitypubEnabled) { - const exists = await posts.exists(pid); - if (!exists) { - await activitypub.notes.assert(req.uid, pid); - } + // Kickstart note assertion if applicable -- might not be needed, if no ill effects, remove 1 Apr 2026 + // if (!utils.isNumber(pid) && req.uid && meta.config.activitypubEnabled) { + // const exists = await posts.exists(pid); + // if (!exists) { + // await activitypub.notes.assert(req.uid, pid); + // } + // } + + if (!req.loggedIn && meta.config.activitypubEnabled && !res.locals.isAPI && !utils.isNumber(pid)) { + return helpers.redirect(res, `/outgoing?url=${encodeURIComponent(pid)}`); } const [canRead, path] = await Promise.all([ diff --git a/src/controllers/write/users.js b/src/controllers/write/users.js index a5cde6dad2..935f6d427f 100644 --- a/src/controllers/write/users.js +++ b/src/controllers/write/users.js @@ -43,17 +43,17 @@ Users.update = async (req, res) => { }; Users.delete = async (req, res) => { - await api.users.delete(req, { ...req.params, password: req.body.password }); + await api.users.delete(req, { ...req.params, password: req.body?.password }); helpers.formatApiResponse(200, res); }; Users.deleteContent = async (req, res) => { - await api.users.deleteContent(req, { ...req.params, password: req.body.password }); + await api.users.deleteContent(req, { ...req.params, password: req.body?.password }); helpers.formatApiResponse(200, res); }; Users.deleteAccount = async (req, res) => { - await api.users.deleteAccount(req, { ...req.params, password: req.body.password }); + await api.users.deleteAccount(req, { ...req.params, password: req.body?.password }); helpers.formatApiResponse(200, res); }; diff --git a/src/cron.js b/src/cron.js new file mode 100644 index 0000000000..02f75f2aba --- /dev/null +++ b/src/cron.js @@ -0,0 +1,99 @@ +'use strict'; + +const nconf = require('nconf'); +const { CronJob } = require('cron'); +const cronstrue = require('cronstrue'); +const winston = require('winston'); + +const db = require('./database'); +const utils = require('./utils'); + +const jobs = Object.create(null); + +exports.markJobsInactive = async function () { + const jobs = await db.getSortedSetRange('cronJobs', 0, -1); + await db.setObject(jobs.map(name => `cronJob:${name}`), { active: 0 }); +}; + +exports.addJob = async function (options) { + const { + name, + cronTime, + onTick, + onComplete = null, + start = true, + runOnInit = false, + runOnAllNodes = false, + } = options; + + const isJobEnabled = nconf.get('runJobs'); + + if (!isJobEnabled && !runOnAllNodes) { + return; + } + + if (!name || !cronTime || typeof onTick !== 'function') { + throw new Error('[cron] Invalid options'); + } + if (Object.hasOwn(jobs, name)) { + throw new Error('[cron] Job with that name already exists'); + } + + const job = new CronJob(cronTime, async function () { + const start = Date.now(); + try { + await db.setObjectField(`cronJob:${name}`, 'running', 1); + await onTick(); + await db.deleteObjectField(`cronJob:${name}`, 'lastError'); + } catch (err) { + winston.error(`[cron] ${err.stack}`); + await db.setObjectField(`cronJob:${name}`, 'lastError', err.stack); + } finally { + await db.setObject(`cronJob:${name}`, { + running: 0, + duration: Date.now() - start, + nextRun: job.nextDate().toMillis(), + }); + } + }, onComplete, start, null, null, runOnInit); + + jobs[name] = job; + + await db.sortedSetAdd('cronJobs', Date.now(), name); + await db.setObject(`cronJob:${name}`, { + name, + cronTime, + cronTimeHuman: cronstrue.toString(cronTime), + nextRun: job.nextDate().toMillis(), + running: runOnInit ? 1 : 0, + active: 1, + }); + winston.verbose(`[cron/jobs] Registered job: ${name} (${cronTime})`); + return job; +}; + +exports.getJobs = async function () { + const jobNames = await db.getSortedSetRange('cronJobs', 0, -1); + const jobs = await db.getObjects(jobNames.map(name => `cronJob:${name}`)); + jobs.forEach((job) => { + if (job) { + job.active = parseInt(job.active, 10) === 1; + job.running = parseInt(job.running, 10) === 1; + job.duration = job.duration || 0; + job.durationReadable = formatDuration(job.duration); + job.nextRunISO = utils.toISOString(job.nextRun); + } + }); + jobs.sort((a, b) => b.cronTimeHuman.localeCompare(a.cronTimeHuman)); + return jobs; +}; + +function formatDuration(ms) { + const totalSeconds = Math.floor(ms / 1000); + const minutes = Math.floor(totalSeconds / 60); + const seconds = totalSeconds % 60; + if (minutes > 0) { + return `${minutes}m${String(seconds).padStart(2, '0')}s`; + } + return `${seconds}s`; +} diff --git a/src/database/mongo.js b/src/database/mongo.js index 310867cef5..4e2ba46a66 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -86,6 +86,9 @@ mongoModule.createIndices = async function () { const collection = mongoModule.client.collection('objects'); await collection.createIndex({ _key: 1, score: -1 }, { background: true }); await collection.createIndex({ _key: 1, value: -1 }, { background: true, unique: true, sparse: true }); + await collection.createIndex( + { members: 1, _key: 1}, { background: true, partialFilterExpression: { members: { $exists: true } } } + ); await collection.createIndex({ expireAt: 1 }, { expireAfterSeconds: 0, background: true }); winston.info('[database] Checking database indices done!'); }; diff --git a/src/database/mongo/sets.js b/src/database/mongo/sets.js index 784b6acd70..66b4baebab 100644 --- a/src/database/mongo/sets.js +++ b/src/database/mongo/sets.js @@ -115,7 +115,7 @@ module.exports = function (module) { await module.client.collection('objects').bulkWrite([ { updateMany: { filter: { _key: filterKey }, update: update } }, - { deleteMany: { filter: { _key: filterKey, members: { $size: 0 } } } }, + { deleteMany: { filter: { _key: filterKey, members: [] } } }, ], { ordered: true }); } @@ -128,8 +128,9 @@ module.exports = function (module) { const item = await module.client.collection('objects').findOne({ _key: key, members: value, }, { - projection: { _id: 0, members: 0 }, + projection: { _id: 0, _key: 1}, }); + return item !== null && item !== undefined; }; @@ -137,15 +138,31 @@ module.exports = function (module) { if (!key || !Array.isArray(values) || !values.length) { return []; } - values = values.map(v => helpers.valueToString(v)); + const stringValues = values.map(v => helpers.valueToString(v)); - const result = await module.client.collection('objects').findOne({ - _key: key, - }, { - projection: { _id: 0, _key: 0 }, - }); - const membersSet = new Set(result && Array.isArray(result.members) ? result.members : []); - return values.map(v => membersSet.has(v)); + const pipeline = [ + { + $match: { + _key: key, + members: { $in: stringValues, $exists: true }, // Trigger the partial index + }, + }, + { + $project: { + _id: 0, + results: { + $map: { + input: stringValues, + as: 'val', + in: { $in: ['$$val', '$members'] }, + }, + }, + }, + }, + ]; + + const [doc] = await module.client.collection('objects').aggregate(pipeline).toArray(); + return doc ? doc.results : values.map(() => false); }; module.isMemberOfSets = async function (sets, value) { @@ -157,7 +174,7 @@ module.exports = function (module) { const result = await module.client.collection('objects').find({ _key: { $in: sets }, members: value, }, { - projection: { _id: 0, members: 0 }, + projection: { _id: 0, _key: 1 }, }).toArray(); const map = {}; @@ -176,7 +193,7 @@ module.exports = function (module) { const data = await module.client.collection('objects').findOne({ _key: key, }, { - projection: { _id: 0, _key: 0 }, + projection: { _id: 0, members: 1 }, }); return data ? data.members : []; }; diff --git a/src/database/mongo/sorted.js b/src/database/mongo/sorted.js index eceea5e342..c6f1ee90ce 100644 --- a/src/database/mongo/sorted.js +++ b/src/database/mongo/sorted.js @@ -393,13 +393,13 @@ module.exports = function (module) { return []; } const arrayOfKeys = keys.length > 1; - const projection = { _id: 0, value: 1 }; + const projection = arrayOfKeys ? + { _id: 0, _key: 1, value: 1} : + { _id: 0, value: 1 }; if (withScores) { projection.score = 1; } - if (arrayOfKeys) { - projection._key = 1; - } + const data = await module.client.collection('objects').find({ _key: arrayOfKeys ? { $in: keys } : keys[0], }, { projection: projection }) diff --git a/src/database/redis/sorted.js b/src/database/redis/sorted.js index 5b9652e6e0..8433133f15 100644 --- a/src/database/redis/sorted.js +++ b/src/database/redis/sorted.js @@ -301,7 +301,7 @@ module.exports = function (module) { const returnData = []; let done; - const seen = Object.create(null); + const seen = new Set(); do { /* eslint-disable no-await-in-loop */ const res = await module.client.zScan(params.key, cursor, { MATCH: params.match, COUNT: 5000 }); @@ -310,11 +310,11 @@ module.exports = function (module) { for (let i = 0; i < res.members.length; i ++) { const item = res.members[i]; - if (!seen[item.value]) { - seen[item.value] = 1; + if (!seen.has(item.value)) { + seen.add(item.value); if (params.withScores) { - returnData.push({ value: item.value, score: parseFloat(item.score) }); + returnData.push({ value: item.value, score: item.score }); } else { returnData.push(item.value); } diff --git a/src/groups/index.js b/src/groups/index.js index e4f24e5335..1e50814a79 100644 --- a/src/groups/index.js +++ b/src/groups/index.js @@ -120,7 +120,7 @@ Groups.getAllGroupNames = async function (set) { return [...names]; } names = await db.getSortedSetRevRange(set, 0, -1); - cache.set(names); + cache.set(cacheKey, names); return [...names]; }; diff --git a/src/groups/invite.js b/src/groups/invite.js index 747111d156..e5b7c7a1ca 100644 --- a/src/groups/invite.js +++ b/src/groups/invite.js @@ -54,9 +54,15 @@ module.exports = function (Groups) { if (!Array.isArray(groupNames)) { groupNames = [groupNames]; } - const sets = []; - groupNames.forEach(groupName => sets.push(`group:${groupName}:pending`, `group:${groupName}:invited`)); - await db.setsRemove(sets, uid); + const sets = [ + ...groupNames.map(g => `group:${g}:pending`), + ...groupNames.map(g => `group:${g}:invited`), + ]; + const isMembers = await db.isMemberOfSets(sets, uid); + const toRemoveSets = sets.filter((set, index) => isMembers[index]); + if (toRemoveSets.length) { + await db.setsRemove(toRemoveSets, uid); + } }; Groups.invite = async function (groupName, uids) { diff --git a/src/meta/errors.js b/src/meta/errors.js index c936b6675f..7b623fe5f0 100644 --- a/src/meta/errors.js +++ b/src/meta/errors.js @@ -3,13 +3,13 @@ const nconf = require('nconf'); const winston = require('winston'); const validator = require('validator'); -const cronJob = require('cron').CronJob; const { setTimeout } = require('timers/promises'); const db = require('../database'); const analytics = require('../analytics'); const pubsub = require('../pubsub'); const utils = require('../utils'); +const cron = require('../cron'); const Errors = module.exports; @@ -19,13 +19,18 @@ let counters = {}; let total = {}; Errors.init = async function () { - new cronJob('0 * * * * *', async () => { - publishLocalErrors(); - if (runJobs) { - await setTimeout(2000); - await Errors.writeData(); - } - }, null, true); + await cron.addJob({ + name: 'errors:publish', + cronTime: '0 * * * * *', + runOnAllNodes: true, + onTick: async () => { + publishLocalErrors(); + if (runJobs) { + await setTimeout(2000); + await Errors.writeData(); + } + }, + }); if (runJobs) { pubsub.on('errors:publish', (data) => { @@ -69,8 +74,10 @@ Errors.log404 = function (route) { if (!route) { return; } - route = route.slice(0, 512).replace(/\/$/, ''); // remove trailing slashes + analytics.increment('errors:404'); + + route = route.slice(0, 512).replace(/\/$/, ''); // remove trailing slashes const segments = route.split('/'); const containsUUID = segments.some((segment) => { const cleanSegment = segment.split('.')[0]; @@ -79,7 +86,7 @@ Errors.log404 = function (route) { if (containsUUID) { return; } - analytics.increment('errors:404'); + counters[route] = counters[route] || 0; counters[route] += 1; }; diff --git a/src/notifications.js b/src/notifications.js index e52be01609..0a108ff03b 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -3,7 +3,6 @@ const async = require('async'); const winston = require('winston'); -const cron = require('cron').CronJob; const nconf = require('nconf'); const _ = require('lodash'); @@ -18,6 +17,8 @@ const plugins = require('./plugins'); const utils = require('./utils'); const emailer = require('./emailer'); const ttlCache = require('./cache/ttl'); +const cron = require('./cron'); +const translator = require('./translator'); const Notifications = module.exports; @@ -73,9 +74,13 @@ Notifications.getAllNotificationTypes = async function () { return results.types.concat(results.privilegedTypes); }; -Notifications.startJobs = function () { +Notifications.startJobs = async function () { winston.verbose('[notifications.init] Registering jobs.'); - new cron('*/30 * * * *', Notifications.prune, null, true); + await cron.addJob({ + name: 'notifications:prune', + cronTime: '*/30 * * * *', + onTick: Notifications.prune, + }); }; Notifications.get = async function (nid) { @@ -514,7 +519,9 @@ Notifications.merge = async function (notifications) { differentiators.forEach((differentiator) => { function typeFromLength(items) { - if (items.length === 2) { + if (items.length <= 1) { + return ''; + } else if (items.length === 2) { return 'dual'; } else if (items.length === 3) { return 'triple'; @@ -538,19 +545,24 @@ Notifications.merge = async function (notifications) { const { roomId, roomName, type, user } = set[0]; const isGroupChat = type === 'new-group-chat'; notifObj.bodyShort = isGroupChat || (roomName !== `[[modules:chat.room-id, ${roomId}]]`) ? - `[[notifications:new-messages-in, ${set.length}, ${roomName}]]` : - `[[notifications:new-messages-from, ${set.length}, ${user.displayname}]]`; + translator.compile('notifications:new-messages-in', set.length, roomName) : + translator.compile('notifications:new-messages-from', set.length, user.displayname); break; } case 'notifications:user-posted-in-public-room': { - const usernames = _.uniq(set.map(notifObj => notifObj && notifObj.user && notifObj.user.displayname)); - if (usernames.length === 2 || usernames.length === 3) { - notifObj.bodyShort = `[[${mergeId}-${typeFromLength(usernames)}, ${usernames.join(', ')}, ${notifObj.roomIcon}, ${notifObj.roomName}]]`; - } else if (usernames.length > 3) { - notifObj.bodyShort = `[[${mergeId}-${typeFromLength(usernames)}, ${usernames.slice(0, 2).join(', ')}, ${usernames.length - 2}, ${notifObj.roomIcon}, ${notifObj.roomName}]]`; - } + const usernames = _.uniq(set.map(n => n?.user?.displayname)).filter(Boolean); + const type = typeFromLength(usernames); + const isMultiple = type === 'multiple'; + const txArgs = [ + `${mergeId}${type ? `-${type}` : ''}`, + ...usernames.slice(0, usernames.length <= 3 ? 3 : 2), + ...(isMultiple ? [usernames.length - 2] : []), + notifObj.roomIcon, + notifObj.roomName, + ]; + notifObj.bodyShort = translator.compile(...txArgs); notifObj.path = set[set.length - 1].path; break; } @@ -560,24 +572,22 @@ Notifications.merge = async function (notifications) { case 'notifications:user-flagged-post-in': case 'notifications:user-flagged-user': case 'notifications:activitypub.announce': { - const usernames = _.uniq(set.map(notifObj => notifObj && notifObj.user && notifObj.user.displayname)); - const numUsers = usernames.length; - - const title = utils.decodeHTMLEntities(notifications[modifyIndex].topicTitle || ''); - let titleEscaped = title.replace(/%/g, '%').replace(/,/g, ','); - titleEscaped = titleEscaped ? (`, ${titleEscaped}`) : ''; - - if (numUsers === 2 || numUsers === 3) { - notifications[modifyIndex].bodyShort = `[[${mergeId}-${typeFromLength(usernames)}, ${usernames.join(', ')}${titleEscaped}]]`; - } else if (numUsers > 2) { - notifications[modifyIndex].bodyShort = `[[${mergeId}-${typeFromLength(usernames)}, ${usernames.slice(0, 2).join(', ')}, ${numUsers - 2}${titleEscaped}]]`; - } - - notifications[modifyIndex].path = set[set.length - 1].path; - } break; + const usernames = _.uniq(set.map(n => n?.user?.displayname)).filter(Boolean); + const type = typeFromLength(usernames); + const isMultiple = type === 'multiple'; + const txArgs = [ + `${mergeId}${type ? `-${type}` : ''}`, + ...usernames.slice(0, usernames.length <= 3 ? 3 : 2), + ...(isMultiple ? [usernames.length - 2] : []), + utils.decodeHTMLEntities(notifObj.topicTitle || ''), + ]; + notifObj.bodyShort = translator.compile(...txArgs); + notifObj.path = set[set.length - 1].path; + break; + } case 'new-register': - notifications[modifyIndex].bodyShort = `[[notifications:${mergeId}-multiple, ${set.length}]]`; + notifObj.bodyShort = `[[notifications:${mergeId}-multiple, ${set.length}]]`; break; } diff --git a/src/plugins/data.js b/src/plugins/data.js index ba6e319e78..0078fa34b8 100644 --- a/src/plugins/data.js +++ b/src/plugins/data.js @@ -55,6 +55,7 @@ Data.loadPluginInfo = async function (pluginPath) { pluginData.description = packageData.description; pluginData.version = packageData.version; pluginData.repository = packageData.repository; + pluginData.url = pluginData.url || pluginData?.repository?.url || ''; pluginData.nbbpm = packageData.nbbpm; pluginData.path = pluginPath; } catch (err) { diff --git a/src/plugins/usage.js b/src/plugins/usage.js index f36370b50f..cc9e2433de 100644 --- a/src/plugins/usage.js +++ b/src/plugins/usage.js @@ -3,18 +3,20 @@ const nconf = require('nconf'); const winston = require('winston'); const crypto = require('crypto'); -const cronJob = require('cron').CronJob; const request = require('../request'); +const cron = require('../cron'); const pkg = require('../../package.json'); const meta = require('../meta'); module.exports = function (Plugins) { - Plugins.startJobs = function () { - new cronJob('0 0 0 * * *', (async () => { - await Plugins.submitUsageData(); - }), null, true); + Plugins.startJobs = async function () { + await cron.addJob({ + name: 'plugins:submitUsageData', + cronTime: '0 0 0 * * *', + onTick: Plugins.submitUsageData, + }); }; Plugins.submitUsageData = async function () { diff --git a/src/posts/parse.js b/src/posts/parse.js index a4d8f57443..ae2bcb713e 100644 --- a/src/posts/parse.js +++ b/src/posts/parse.js @@ -10,6 +10,7 @@ const plugins = require('../plugins'); const translator = require('../translator'); const utils = require('../utils'); const postCache = require('./cache'); +const devMode = process.env.NODE_ENV === 'development'; let sanitizeConfig = { allowedTags: sanitize.defaults.allowedTags.concat([ @@ -99,7 +100,9 @@ module.exports = function (Posts) { content.slice(current.index + offset + current[1].length); } } catch (err) { - winston.verbose(err.messsage); + if (devMode) { + winston.verbose(err.messsage); + } } } current = regex.exec(content); diff --git a/src/posts/uploads.js b/src/posts/uploads.js index 372c30ca1e..84b9ce283b 100644 --- a/src/posts/uploads.js +++ b/src/posts/uploads.js @@ -7,7 +7,6 @@ const path = require('path'); const winston = require('winston'); const mime = require('mime'); const validator = require('validator'); -const cronJob = require('cron').CronJob; const chalk = require('chalk'); const db = require('../database'); @@ -16,6 +15,7 @@ const user = require('../user'); const topics = require('../topics'); const file = require('../file'); const meta = require('../meta'); +const cron = require('../cron'); module.exports = function (Posts) { Posts.uploads = {}; @@ -30,18 +30,26 @@ module.exports = function (Posts) { return fullPath.startsWith(pathPrefix) && await file.exists(fullPath) ? filePath : false; }))).filter(Boolean); - const runJobs = nconf.get('runJobs'); - if (runJobs) { - new cronJob('0 2 * * 0', async () => { - const orphans = await Posts.uploads.cleanOrphans(); - if (orphans.length) { - winston.info(`[posts/uploads] Deleting ${orphans.length} orphaned uploads...`); - orphans.forEach((relPath) => { - process.stdout.write(`${chalk.red(' - ')} ${relPath}`); - }); - } - }, null, true); - } + Posts.uploads.startJobs = async function () { + const runJobs = nconf.get('runJobs'); + if (!runJobs) { + return; + } + + await cron.addJob({ + name: 'posts:uploads:cleanupOrphans', + cronTime: '0 2 * * 0', + onTick: async () => { + const orphans = await Posts.uploads.cleanOrphans(); + if (orphans.length) { + winston.info(`[posts/uploads] Deleting ${orphans.length} orphaned uploads...`); + orphans.forEach((relPath) => { + process.stdout.write(`${chalk.red(' - ')} ${relPath}`); + }); + } + }, + }); + }; Posts.uploads.sync = async function (pid) { // Scans a post's content and updates sorted set of uploads diff --git a/src/privileges/admin.js b/src/privileges/admin.js index 422e9c1060..8e40029786 100644 --- a/src/privileges/admin.js +++ b/src/privileges/admin.js @@ -67,6 +67,7 @@ privsAdmin.routeMap = { uploadfavicon: 'admin:settings', uploadTouchIcon: 'admin:settings', uploadMaskableIcon: 'admin:settings', + uploadScreenshot: 'admin:settings', uploadlogo: 'admin:settings', uploadOgImage: 'admin:settings', uploadDefaultAvatar: 'admin:settings', @@ -115,7 +116,6 @@ privsAdmin.socketMap = { 'admin.getSearchDict': 'admin:settings', 'admin.config.setMultiple': 'admin:settings', 'admin.config.remove': 'admin:settings', - 'admin.themes.getInstalled': 'admin:settings', 'admin.themes.set': 'admin:settings', 'admin.reloadAllSessions': 'admin:settings', 'admin.settings.get': 'admin:settings', diff --git a/src/routes/activitypub.js b/src/routes/activitypub.js index 00d8b1a125..6c13fea365 100644 --- a/src/routes/activitypub.js +++ b/src/routes/activitypub.js @@ -6,7 +6,6 @@ module.exports = function (app, middleware, controllers) { helpers.setupPageRoute(app, '/world', [ middleware.activitypub.enabled, middleware.activitypub.pageview, - middleware.ensureLoggedIn, ], controllers.activitypub.topics.list); helpers.setupPageRoute(app, '/ap', [ middleware.activitypub.enabled, diff --git a/src/routes/admin.js b/src/routes/admin.js index 03eb002e5f..768e457409 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -74,6 +74,7 @@ module.exports = function (app, name, middleware, controllers) { helpers.setupAdminPageRoute(app, `/${name}/advanced/errors`, middlewares, controllers.admin.errors.get); helpers.setupAdminPageRoute(app, `/${name}/advanced/errors/export`, middlewares, controllers.admin.errors.export); helpers.setupAdminPageRoute(app, `/${name}/advanced/cache`, middlewares, controllers.admin.cache.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/jobs`, middlewares, controllers.admin.jobs.get); helpers.setupAdminPageRoute(app, `/${name}/development/logger`, middlewares, controllers.admin.logger.get); helpers.setupAdminPageRoute(app, `/${name}/development/info`, middlewares, controllers.admin.info.get); @@ -105,6 +106,7 @@ function apiRoutes(router, name, middleware, controllers) { router.post(`/api/${name}/uploadfavicon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFavicon)); router.post(`/api/${name}/uploadTouchIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadTouchIcon)); router.post(`/api/${name}/uploadMaskableIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadMaskableIcon)); + router.post(`/api/${name}/uploadScreenshot`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadScreenshot)); router.post(`/api/${name}/uploadlogo`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadLogo)); router.post(`/api/${name}/uploadOgImage`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadOgImage)); router.post(`/api/${name}/upload/file`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFile)); diff --git a/src/socket.io/admin/themes.js b/src/socket.io/admin/themes.js index 7c8ad7da74..017f6d0c2c 100644 --- a/src/socket.io/admin/themes.js +++ b/src/socket.io/admin/themes.js @@ -5,10 +5,6 @@ const widgets = require('../../widgets'); const Themes = module.exports; -Themes.getInstalled = async function () { - return await meta.themes.get(); -}; - Themes.set = async function (socket, data) { if (!data) { throw new Error('[[error:invalid-data]]'); diff --git a/src/socket.io/index.js b/src/socket.io/index.js index fdcf6146b0..ca80a9e057 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -1,6 +1,5 @@ 'use strict'; -const _ = require('lodash'); const os = require('os'); const nconf = require('nconf'); const winston = require('winston'); @@ -318,16 +317,16 @@ Sockets.getUidsInRoom = async function (room) { return []; } const ioRoom = Sockets.server.in(room); - const uids = []; + const uids = new Set(); if (ioRoom) { const sockets = await ioRoom.fetchSockets(); for (const s of sockets) { if (s && s.data && s.data.uid > 0) { - uids.push(s.data.uid); + uids.add(s.data.uid); } } } - return _.uniq(uids); + return [...uids]; }; Sockets.warnDeprecated = (socket, replacement) => { diff --git a/src/socket.io/user/picture.js b/src/socket.io/user/picture.js index 828dca61f8..d63f28e61c 100644 --- a/src/socket.io/user/picture.js +++ b/src/socket.io/user/picture.js @@ -1,5 +1,9 @@ 'use strict'; +const validator = require('validator'); +const nconf = require('nconf'); + +const db = require('../../database'); const user = require('../../user'); const plugins = require('../../plugins'); @@ -10,7 +14,7 @@ module.exports = function (SocketUser) { } await user.isAdminOrSelf(socket.uid, data.uid); // 'keepAllUserImages' is ignored, since there is explicit user intent - const userData = await user.removeProfileImage(data.uid); + const userData = await user.removeProfileImage(data.uid, data.picture); plugins.hooks.fire('action:user.removeUploadedPicture', { callerUid: socket.uid, uid: data.uid, @@ -23,27 +27,29 @@ module.exports = function (SocketUser) { throw new Error('[[error:invalid-data]]'); } - const [list, userObj] = await Promise.all([ + const [list, userObj, userPictures] = await Promise.all([ plugins.hooks.fire('filter:user.listPictures', { uid: data.uid, pictures: [], }), user.getUserData(data.uid), + db.getSortedSetRevRange(`uid:${data.uid}:profile:pictures`, 0, 2), ]); - if (userObj.uploadedpicture) { + userPictures.forEach((picture) => { list.pictures.push({ type: 'uploaded', - url: userObj.uploadedpicture, + url: `${nconf.get('relative_path')}${picture}`, text: '[[user:uploaded-picture]]', }); - } + }); // Normalize list into "user object" format list.pictures = list.pictures.map(({ type, url, text }) => ({ type, username: text, - picture: url, + picture: validator.escape(String(url)), + selected: url === userObj.picture, })); list.pictures.unshift({ @@ -51,6 +57,7 @@ module.exports = function (SocketUser) { 'icon:text': userObj['icon:text'], 'icon:bgColor': userObj['icon:bgColor'], username: '[[user:default-picture]]', + selected: !userObj.picture, }); return list.pictures; diff --git a/src/start.js b/src/start.js index 2928ac6bb6..00a129e33f 100644 --- a/src/start.js +++ b/src/start.js @@ -35,11 +35,13 @@ start.start = async function () { await sockets.init(webserver.server); if (nconf.get('runJobs')) { - require('./notifications').startJobs(); - require('./user').startJobs(); - require('./plugins').startJobs(); - require('./topics').scheduled.startJobs(); - require('./activitypub').jobs.start(); + await require('./cron').markJobsInactive(); + await require('./notifications').startJobs(); + await require('./user').startJobs(); + await require('./plugins').startJobs(); + await require('./topics').scheduled.startJobs(); + await require('./posts').uploads.startJobs(); + await require('./activitypub').jobs.start(); await db.delete('locks'); } diff --git a/src/topics/scheduled.js b/src/topics/scheduled.js index a20109a50d..b6dcba9a74 100644 --- a/src/topics/scheduled.js +++ b/src/topics/scheduled.js @@ -2,7 +2,6 @@ const _ = require('lodash'); const winston = require('winston'); -const { CronJob } = require('cron'); const db = require('../database'); const posts = require('../posts'); @@ -13,18 +12,17 @@ const groups = require('../groups'); const user = require('../user'); const activitypub = require('../activitypub'); const plugins = require('../plugins'); +const cron = require('../cron'); const Scheduled = module.exports; -Scheduled.startJobs = function () { +Scheduled.startJobs = async function () { winston.verbose('[scheduled topics] Starting jobs.'); - new CronJob('*/1 * * * *', async () => { - try { - await Scheduled.handleExpired(); - } catch (err) { - winston.error(err.stack); - } - }, null, true); + await cron.addJob({ + name: 'topics:publish:scheduled', + cronTime: '*/1 * * * *', + onTick: Scheduled.handleExpired, + }); }; Scheduled.handleExpired = async function () { diff --git a/src/topics/sorted.js b/src/topics/sorted.js index 1d4da1f772..a37d249cb0 100644 --- a/src/topics/sorted.js +++ b/src/topics/sorted.js @@ -46,7 +46,8 @@ module.exports = function (Topics) { let tids; if (params.term !== 'alltime') { if (params.sort === 'posts') { - tids = await getTidsWithMostPostsInTerm(params.cids, params.uid, params.term); + const { cids, uid, term, includeRemote } = params; + tids = await getTidsWithMostPostsInTerm({ cids, uid, term, includeRemote }); } else { const cids = await getCids(params.cids, params.uid); tids = await Topics.getLatestTidsFromSet( @@ -74,17 +75,18 @@ module.exports = function (Topics) { } async function getInbox(tids, params) { - if (!Array.isArray(params.cids) || !params.cids.includes('-1')) { + if (!params.includeRemote) { return tids; } let inbox; + const set = params.followingOnly ? `uid:${params.uid}:inbox` : 'cid:-1:tids'; if (params.term !== 'alltime') { const method = params.sort === 'old' ? 'getSortedSetRangeByScore' : 'getSortedSetRevRangeByScore'; inbox = await db[method]( - `uid:${params.uid}:inbox`, + set, 0, 1000, '+inf', @@ -94,7 +96,7 @@ module.exports = function (Topics) { const method = params.sort === 'old' ? 'getSortedSetRange' : 'getSortedSetRevRange'; - inbox = await db[method](`uid:${params.uid}:inbox`, 0, meta.config.recentMaxTopics - 1); + inbox = await db[method](set, 0, meta.config.recentMaxTopics - 1); } return _.uniq(tids.concat(inbox)); @@ -115,20 +117,26 @@ module.exports = function (Topics) { return 'topics:recent'; } - async function getCids(cids, uid) { + async function getCids(cids, uid, includeRemote) { if (Array.isArray(cids)) { cids = await privileges.categories.filterCids('topics:read', cids, uid); } else { cids = await categories.getCidsByPrivilege('categories:cid', uid, 'topics:read'); cids = cids.filter(cid => cid !== -1); } + + if (includeRemote) { + const remoteCids = await db.getObjectValues('handle:cid'); + cids = [-1, ...cids, ...remoteCids]; + } return cids; } - async function getTidsWithMostPostsInTerm(cids, uid, term) { - cids = await getCids(cids, uid); + async function getTidsWithMostPostsInTerm({ cids, uid, term, includeRemote }) { + cids = await getCids(cids, uid, includeRemote); + const sets = cids.map(cid => `cid:${cid}:pids`); const pids = await db.getSortedSetRevRangeByScore( - cids.map(cid => `cid:${cid}:pids`), + sets, 0, 1000, '+inf', @@ -200,7 +208,7 @@ module.exports = function (Topics) { } async function sortTids(tids, params) { - if (params.term === 'alltime' && !params.cids && !params.tags.length && params.filter !== 'watched' && !params.floatPinned) { + if (params.term === 'alltime' && !params.cids && !params.tags.length && params.filter !== 'watched' && !params.floatPinned && !params.includeRemote) { return tids; } diff --git a/src/topics/tags.js b/src/topics/tags.js index 7f60096cd1..48bbb44e15 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -256,14 +256,21 @@ module.exports = function (Topics) { }; async function removeTagsFromTopics(tags) { - await async.eachLimit(tags, 50, async (tag) => { - const tids = await db.getSortedSetRange(`tag:${tag}:topics`, 0, -1); - if (!tids.length) { - return; - } + const uniqTids = new Set(); + const tagsToRemove = new Set(tags); + + await batch.processArray(tags, async (tags) => { + await Promise.all(tags.map(async (tag) => { + await batch.processSortedSet(`tag:${tag}:topics`, async (tids) => { + tids.forEach(tid => uniqTids.add(tid)); + }, { batch: 500 }); + })); + }, { batch: 50 }); + + await batch.processArray(Array.from(uniqTids), async (tids) => { let topicsTags = await Topics.getTopicsTags(tids); topicsTags = topicsTags.map( - topicTags => topicTags.filter(topicTag => topicTag && topicTag !== tag) + topicTags => topicTags.filter(tag => tag && !tagsToRemove.has(tag)) ); await db.setObjectBulk( @@ -271,7 +278,7 @@ module.exports = function (Topics) { `topic:${tid}`, { tags: topicsTags[index].join(',') }, ])) ); - }); + }, { batch: 500 }); } async function removeTagsFromUsers(tags) { diff --git a/src/topics/thumbs.js b/src/topics/thumbs.js index 013e82a483..123f84f026 100644 --- a/src/topics/thumbs.js +++ b/src/topics/thumbs.js @@ -45,13 +45,22 @@ Thumbs.load = async function (topicData, options = {}) { async function loadFromTopicData(topicData, options = {}) { const tids = topicData.map(t => t && t.tid); const thumbs = topicData.map(t => t && Array.isArray(t.thumbs) ? t.thumbs : []); + const mainPids = topicData.map(t => t.mainPid); + + const mainPidAttachments = await posts.attachments.get(mainPids); + // Add attachments to thumb sets + mainPidAttachments.forEach((attachments, idx) => { + attachments = attachments.filter( + attachment => !thumbs[idx].includes(attachment.url) && (attachment.mediaType && attachment.mediaType.startsWith('image/')) + ); + + if (attachments.length) { + thumbs[idx].push(...attachments.map(attachment => attachment.url)); + } + }); if (!options.thumbsOnly) { - const mainPids = topicData.map(t => t.mainPid); - const [mainPidUploads, mainPidAttachments] = await Promise.all([ - posts.uploads.list(mainPids), - posts.attachments.get(mainPids), - ]); + const mainPidUploads = await posts.uploads.list(mainPids); // Add uploaded media to thumb sets mainPidUploads.forEach((uploads, idx) => { @@ -64,17 +73,6 @@ async function loadFromTopicData(topicData, options = {}) { thumbs[idx].push(...uploads); } }); - - // Add attachments to thumb sets - mainPidAttachments.forEach((attachments, idx) => { - attachments = attachments.filter( - attachment => !thumbs[idx].includes(attachment.url) && (attachment.mediaType && attachment.mediaType.startsWith('image/')) - ); - - if (attachments.length) { - thumbs[idx].push(...attachments.map(attachment => attachment.url)); - } - }); } const hasTimestampPrefix = /^\d+-/; diff --git a/src/upgrades/3.2.0/fix_username_zsets.js b/src/upgrades/3.2.0/fix_username_zsets.js index 22ab35c152..01c2663a04 100644 --- a/src/upgrades/3.2.0/fix_username_zsets.js +++ b/src/upgrades/3.2.0/fix_username_zsets.js @@ -11,9 +11,28 @@ module.exports = { method: async function () { const { progress } = this; - await db.deleteAll(['username:uid', 'username:sorted']); + const [userNameUid, usernameSorted, usersJoindate] = await db.sortedSetsCard([ + 'username:uid', 'username:sorted', 'users:joindate', + ]); + progress.total = userNameUid + usernameSorted + usersJoindate; + + await batch.processSortedSet('username:uid', async (usernames) => { + await db.sortedSetRemove('username:uid', usernames); + progress.incr(usernames.length); + }, { + batch: 500, + alwaysStartAt: 0, + }); + + await batch.processSortedSet('username:sorted', async (usernames) => { + await db.sortedSetRemove('username:sorted', usernames); + progress.incr(usernames.length); + }, { + batch: 500, + alwaysStartAt: 0, + }); + await batch.processSortedSet('users:joindate', async (uids) => { - progress.incr(uids.length); const usersData = await db.getObjects(uids.map(uid => `user:${uid}`)); const bulkAdd = []; usersData.forEach((userData) => { @@ -23,9 +42,9 @@ module.exports = { } }); await db.sortedSetAddBulk(bulkAdd); + progress.incr(uids.length); }, { batch: 500, - progress: progress, }); }, }; diff --git a/src/upgrades/4.10.0/mongodb-set-members-index.js b/src/upgrades/4.10.0/mongodb-set-members-index.js new file mode 100644 index 0000000000..f7a2284eb7 --- /dev/null +++ b/src/upgrades/4.10.0/mongodb-set-members-index.js @@ -0,0 +1,22 @@ +'use strict'; + + +const db = module.parent.require('./database'); + +module.exports = { + name: 'Add a partial index on set members', + timestamp: Date.UTC(2026, 2, 11), + method: async function () { + const nconf = require.main.require('nconf'); + const isMongo = nconf.get('database') === 'mongo'; + if (!isMongo) { + return; + } + + await db.client.collection('objects').createIndex( + { members: 1, _key: 1 }, + { background: true, partialFilterExpression: { members: { $exists: true } } }, + ); + }, +}; + diff --git a/src/upgrades/4.10.0/user-profile-pictures-zset.js b/src/upgrades/4.10.0/user-profile-pictures-zset.js new file mode 100644 index 0000000000..98ce8f9e4f --- /dev/null +++ b/src/upgrades/4.10.0/user-profile-pictures-zset.js @@ -0,0 +1,23 @@ +'use strict'; + +const db = require('../../database'); +const batch = require('../../batch'); + +module.exports = { + name: 'Add uid::profile:pictures zset', + timestamp: Date.UTC(2026, 2, 13), + method: async function () { + const { progress } = this; + await batch.processSortedSet('users:joindate', async (uids) => { + const userData = await db.getObjects(uids.map(uid => `user:${uid}`)); + const now = Date.now(); + const bulkAdd = userData.filter(u => u && u.uploadedpicture) + .map(u => ([`uid:${u.uid}:profile:pictures`, now, u.uploadedpicture])); + await db.sortedSetAddBulk(bulkAdd); + progress.incr(uids.length); + }, { + batch: 500, + progress, + }); + }, +}; diff --git a/src/user/approval.js b/src/user/approval.js index c0e654438c..c54f057841 100644 --- a/src/user/approval.js +++ b/src/user/approval.js @@ -2,7 +2,6 @@ const validator = require('validator'); const winston = require('winston'); -const cronJob = require('cron').CronJob; const db = require('../database'); const meta = require('../meta'); @@ -14,14 +13,6 @@ const slugify = require('../slugify'); const plugins = require('../plugins'); module.exports = function (User) { - new cronJob('0 * * * *', (async () => { - try { - await User.autoApprove(); - } catch (err) { - winston.error(err.stack); - } - }), null, true); - User.createOrQueue = async function (req, userData, opts = {}) { User.checkUsernameLength(userData.username); const queue = await User.shouldQueueUser(req.ip); diff --git a/src/user/data.js b/src/user/data.js index d45e4a6259..fbe9fd75da 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -376,7 +376,8 @@ module.exports = function (User) { const _iconBackgrounds = [ '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#009688', '#1b5e20', '#33691e', '#827717', '#e65100', '#ff5722', - '#795548', '#607d8b', + '#795548', '#607d8b', '#00bcd4', '#ffc107', '#8bc34a', '#9e9e9e', + '#004d40', '#ad1457', ]; const data = await plugins.hooks.fire('filter:user.iconBackgrounds', { iconBackgrounds: _iconBackgrounds }); diff --git a/src/user/delete.js b/src/user/delete.js index 12cdbb588d..3de2127ed0 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -1,6 +1,5 @@ 'use strict'; -const async = require('async'); const _ = require('lodash'); const path = require('path'); const nconf = require('nconf'); @@ -60,8 +59,9 @@ module.exports = function (User) { } async function deleteUploads(callerUid, uid) { - const uploads = await db.getSortedSetMembers(`uid:${uid}:uploads`); - await User.deleteUpload(callerUid, uid, uploads); + await batch.processSortedSet(`uid:${uid}:uploads`, async (uploads) => { + await User.deleteUpload(callerUid, uid, uploads); + }, { alwaysStartAt: 0, batch: 500 }); } async function deleteQueued(uid) { @@ -71,7 +71,11 @@ module.exports = function (User) { const userQueuedIds = data.filter(d => String(d.uid) === String(uid)).map(d => d.id); deleteIds = deleteIds.concat(userQueuedIds); }, { batch: 500 }); - await async.eachSeries(deleteIds, posts.removeFromQueue); + + for (const id of deleteIds) { + // eslint-disable-next-line no-await-in-loop + await posts.removeFromQueue(id); + } } async function removeFromSortedSets(uid) { @@ -130,6 +134,7 @@ module.exports = function (User) { `uid:${uid}:flag:pids`, `uid:${uid}:sessions`, `uid:${uid}:shares`, + `uid:${uid}:profile:images`, `invitation:uid:${uid}`, ]; @@ -195,9 +200,10 @@ module.exports = function (User) { `uid:${uid}:upvote`, `uid:${uid}:downvote`, ], 0, -1); const pids = _.uniq(upvoteDownvotePids).filter(Boolean); - await async.eachSeries(pids, async (pid) => { + for (const pid of pids) { + // eslint-disable-next-line no-await-in-loop await posts.unvote(pid, uid); - }); + } } async function deleteChats(uid) { diff --git a/src/user/follow.js b/src/user/follow.js index 7e561d07e5..d14251d38c 100644 --- a/src/user/follow.js +++ b/src/user/follow.js @@ -58,15 +58,32 @@ module.exports = function (User) { ]); } - const [followingCount, followingRemoteCount, followerCount, followerRemoteCount] = await db.sortedSetsCard([ - `following:${uid}`, `followingRemote:${uid}`, `followers:${theiruid}`, `followersRemote:${theiruid}`, - ]); - await Promise.all([ - User.setUserField(uid, 'followingCount', followingCount + followingRemoteCount), - User.setUserField(theiruid, 'followerCount', followerCount + followerRemoteCount), - ]); + User.syncFollowCounts(uid, true, false); + User.syncFollowCounts(theiruid, false, true); } + User.syncFollowCounts = async function (uid, following, followers) { + const sets = []; + const property = []; + if (following) { + property.push('followingCount'); + sets.push(`following:${uid}`, `followingRemote:${uid}`); + } + if (followers) { + property.push('followerCount'); + sets.push(`followers:${uid}`, `followersRemote:${uid}`); + }; + + const values = await db.sortedSetsCard(sets); + const payload = property.reduce((payload, cur, idx) => { + const sum = values[idx * 2] + values[(idx * 2) + 1]; + payload[cur] = sum; + return payload; + }, {}); + + await User.setUserFields(uid, payload); + }; + User.getFollowing = async function (uid, start, stop) { return await getFollow(uid, 'following', start, stop); }; diff --git a/src/user/jobs.js b/src/user/jobs.js index 34c797e9e5..2688ba0809 100644 --- a/src/user/jobs.js +++ b/src/user/jobs.js @@ -1,14 +1,14 @@ 'use strict'; const winston = require('winston'); -const cronJob = require('cron').CronJob; const db = require('../database'); const meta = require('../meta'); +const cron = require('../cron'); const jobs = {}; module.exports = function (User) { - User.startJobs = function () { + User.startJobs = async function () { winston.verbose('[user/jobs] (Re-)starting jobs...'); let { digestHour } = meta.config; @@ -22,20 +22,31 @@ module.exports = function (User) { User.stopJobs(); - startDigestJob('digest.daily', `0 ${digestHour} * * *`, 'day'); - startDigestJob('digest.weekly', `0 ${digestHour} * * 0`, 'week'); - startDigestJob('digest.monthly', `0 ${digestHour} 1 * *`, 'month'); + await startDigestJob('digest.daily', `0 ${digestHour} * * *`, 'day'); + await startDigestJob('digest.weekly', `0 ${digestHour} * * 0`, 'week'); + await startDigestJob('digest.monthly', `0 ${digestHour} 1 * *`, 'month'); - jobs['reset.clean'] = new cronJob('0 0 * * *', User.reset.clean, null, true); - winston.verbose('[user/jobs] Starting job (reset.clean)'); + jobs['reset.clean'] = await cron.addJob({ + name: 'user:reset:clean', + cronTime: '0 0 * * *', + onTick: User.reset.clean, + }); + + await cron.addJob({ + name: 'user:autoApprove', + cronTime: '0 * * * *', + onTick: User.autoApprove, + }); winston.verbose(`[user/jobs] jobs started`); }; - function startDigestJob(name, cronString, term) { - jobs[name] = new cronJob(cronString, (async () => { - winston.verbose(`[user/jobs] Digest job (${name}) started.`); - try { + async function startDigestJob(name, cronString, term) { + const newJob = await cron.addJob({ + name, + cronTime: cronString, + onTick: async () => { + winston.verbose(`[user/jobs] Digest job (${name}) started.`); if (name === 'digest.weekly') { const counter = await db.increment('biweeklydigestcounter'); if (counter % 2) { @@ -43,24 +54,27 @@ module.exports = function (User) { } } await User.digest.execute({ interval: term }); - } catch (err) { - winston.error(err.stack); - } - }), null, true); - winston.verbose(`[user/jobs] Starting job (${name})`); + }, + }); + if (newJob) { + jobs[name] = newJob; + } } User.stopJobs = function () { let terminated = 0; // Terminate any active cron jobs - for (const jobId of Object.keys(jobs)) { - winston.verbose(`[user/jobs] Terminating job (${jobId})`); - jobs[jobId].stop(); - delete jobs[jobId]; + for (const [name, job] of Object.entries(jobs)) { + winston.info(`[user/jobs] Terminating job (${name})`); + if (job) { + job.stop(); + delete jobs[name]; + } + terminated += 1; } if (terminated > 0) { - winston.verbose(`[user/jobs] ${terminated} jobs terminated`); + winston.info(`[user/jobs] ${terminated} jobs terminated`); } }; }; diff --git a/src/user/picture.js b/src/user/picture.js index 9e7eaf6d00..db135b463f 100644 --- a/src/user/picture.js +++ b/src/user/picture.js @@ -52,7 +52,10 @@ module.exports = function (User) { const filename = `${data.uid}-profilecover-${Date.now()}${extension}`; const uploadData = await image.uploadImage(filename, `profile/uid-${data.uid}`, picture); - await deleteCurrentPicture(data.uid, 'cover:url'); + if (!meta.config['profile:keepAllUserImages']) { + await deletePicture(data.uid, 'cover:url'); + } + await User.setUserField(data.uid, 'cover:url', uploadData.url); if (data.position) { @@ -87,30 +90,11 @@ module.exports = function (User) { throw new Error('[[error:invalid-image-extension]]'); } - const normalizedPath = await convertToPNG(userPhoto.path); - const isNormalized = userPhoto.path !== normalizedPath; - - await image.resizeImage({ - path: normalizedPath, - type: isNormalized ? 'image/png' : userPhoto.type, - width: meta.config.profileImageDimension, - height: meta.config.profileImageDimension, + return await storeUserUploadedPicture(data.callerUid, data.uid, { + path: userPhoto.path, + type: userPhoto.type, + extension, }); - - const filename = generateProfileImageFilename(data.uid, extension); - const uploadedImage = await image.uploadImage(filename, `profile/uid-${data.uid}`, { - uid: data.uid, - path: normalizedPath, - name: 'profileAvatar', - }); - - await deleteCurrentPicture(data.uid, 'uploadedpicture'); - await User.updateProfile(data.callerUid, { - uid: data.uid, - uploadedpicture: uploadedImage.url, - picture: uploadedImage.url, - }, ['uploadedpicture', 'picture']); - return uploadedImage; }; // uploads image data in base64 as profile picture @@ -133,40 +117,67 @@ module.exports = function (User) { } picture.path = await image.writeImageDataToTempFile(data.imageData); - const normalizedPath = await convertToPNG(picture.path); - const isNormalized = picture.path !== normalizedPath; - picture.path = normalizedPath; - await image.resizeImage({ + + return await storeUserUploadedPicture(data.callerUid, data.uid, { path: picture.path, - type: isNormalized ? 'image/png' : type, - width: meta.config.profileImageDimension, - height: meta.config.profileImageDimension, + type, + extension, }); - - const filename = generateProfileImageFilename(data.uid, extension); - const uploadedImage = await image.uploadImage(filename, `profile/uid-${data.uid}`, picture); - - await deleteCurrentPicture(data.uid, 'uploadedpicture'); - await User.updateProfile(data.callerUid, { - uid: data.uid, - uploadedpicture: uploadedImage.url, - picture: uploadedImage.url, - }, ['uploadedpicture', 'picture']); - return uploadedImage; } finally { await file.delete(picture.path); } }; - async function deleteCurrentPicture(uid, field) { - if (meta.config['profile:keepAllUserImages']) { - return; + async function storeUserUploadedPicture(callerUid, updateUid, picture) { + const { type, extension } = picture; + const normalizedPath = await convertToPNG(picture.path); + const isNormalized = picture.path !== normalizedPath; + + await image.resizeImage({ + path: normalizedPath, + type: isNormalized ? 'image/png' : type, + width: meta.config.profileImageDimension, + height: meta.config.profileImageDimension, + }); + + const filename = generateProfileImageFilename(updateUid, extension); + const uploadedImage = await image.uploadImage(filename, `profile/uid-${updateUid}`, { + uid: updateUid, + path: picture.path, + name: 'profileAvatar', + }); + + await User.updateProfile(callerUid, { + uid: updateUid, + uploadedpicture: uploadedImage.url, + picture: uploadedImage.url, + }, ['uploadedpicture', 'picture']); + + const zsetKey = `uid:${updateUid}:profile:pictures`; + + if (!meta.config['profile:keepAllUserImages']) { + // if we are not keeping all images, only keep most recent 3 + const imagesToKeep = 3; + const previousImages = await db.getSortedSetRevRangeWithScores(zsetKey, 0, -1); + const toDeleteImages = previousImages.filter((imagePath, index) => index >= imagesToKeep - 1) + .map(image => image.value); + const toRemove = [ + ...toDeleteImages.map(imagePath => ([zsetKey, imagePath])), + ]; + + await db.sortedSetRemoveBulk(toRemove); + toDeleteImages.forEach((imagePath) => { + if (imagePath && !imagePath.startsWith('http')) { + file.delete(imagePath); + } + }); } - await deletePicture(uid, field); + await db.sortedSetAdd(zsetKey, Date.now(), uploadedImage.url); + return { url: uploadedImage.url }; } async function deletePicture(uid, field) { - const uploadPath = await getPicturePath(uid, field); + const uploadPath = await getPicturePathFromUserField(uid, field); if (uploadPath) { await file.delete(uploadPath); } @@ -207,31 +218,56 @@ module.exports = function (User) { await db.deleteObjectFields(`user:${data.uid}`, ['cover:url', 'cover:position']); }; - User.removeProfileImage = async function (uid) { + // this function expects a path without nconf.get('relative_path) prepended + User.isUserUploadedPicture = async (uid, picture) => { + return await db.isSortedSetMember(`uid:${uid}:profile:pictures`, picture); + }; + + User.removeProfileImage = async function (uid, picture) { const userData = await User.getUserFields(uid, ['uploadedpicture', 'picture']); - await deletePicture(uid, 'uploadedpicture'); - await User.setUserFields(uid, { - uploadedpicture: '', - // if current picture is uploaded picture, reset to user icon - picture: userData.uploadedpicture === userData.picture ? '' : userData.picture, - }); + if (!picture) { + picture = userData.uploadedpicture; + } + // picture has relative_path prepended, db entries don't have it, so remove it + const cleanPath = picture.replace(new RegExp(`^${nconf.get('relative_path')}`), ''); + const isUserPicture = await User.isUserUploadedPicture(uid, cleanPath); + if (isUserPicture) { + const path = getPicturePath(uid, picture); + await Promise.all([ + path && !path.startsWith('http') ? file.delete(path) : null, + db.sortedSetRemove(`uid:${uid}:profile:pictures`, cleanPath), + ]); + if (picture === userData.picture) { + // if deleting current uploaded picture, reset to user icon + await User.setUserFields(uid, { + uploadedpicture: '', + picture: '', + }); + } + } + return userData; }; User.getLocalCoverPath = async function (uid) { - return getPicturePath(uid, 'cover:url'); + return await getPicturePathFromUserField(uid, 'cover:url'); }; User.getLocalAvatarPath = async function (uid) { - return getPicturePath(uid, 'uploadedpicture'); + return await getPicturePathFromUserField(uid, 'uploadedpicture'); }; - async function getPicturePath(uid, field) { + async function getPicturePathFromUserField(uid, field) { const value = await User.getUserField(uid, field); + return getPicturePath(uid, value); + } + + function getPicturePath(uid, value) { if (!value || !value.startsWith(`${nconf.get('relative_path')}/assets/uploads/profile/uid-${uid}`)) { return false; } const filename = value.split('/').pop(); return path.join(nconf.get('upload_path'), `profile/uid-${uid}`, filename); } + }; diff --git a/src/user/uploads.js b/src/user/uploads.js index b373d48b6b..7d004fdc37 100644 --- a/src/user/uploads.js +++ b/src/user/uploads.js @@ -2,7 +2,6 @@ const path = require('path'); const nconf = require('nconf'); -const winston = require('winston'); const crypto = require('crypto'); const db = require('../database'); @@ -61,12 +60,9 @@ module.exports = function (User) { const fullPaths = uploadNames.map(path => _getFullPath(path)); await Promise.all(fullPaths.map(async (fullPath, idx) => { - winston.verbose(`[user/deleteUpload] Deleting ${uploadNames[idx]}`); await Promise.all([ file.delete(fullPath), file.delete(file.appendToFileName(fullPath, '-resized')), - ]); - await Promise.all([ db.sortedSetRemove(`uid:${uid}:uploads`, uploadNames[idx]), db.delete(`upload:${md5(uploadNames[idx])}`), ]); diff --git a/src/views/404.tpl b/src/views/404.tpl index e0a3d68ed2..482e16ecd9 100644 --- a/src/views/404.tpl +++ b/src/views/404.tpl @@ -3,7 +3,7 @@
    -
    +
    {{{ if error }}}{error}{{{ else }}}[[global:404.message, {config.relative_path}]]{{{ end }}} diff --git a/src/views/admin/advanced/cache.tpl b/src/views/admin/advanced/cache.tpl index a0efd3ff3e..b7d58b8beb 100644 --- a/src/views/admin/advanced/cache.tpl +++ b/src/views/admin/advanced/cache.tpl @@ -23,7 +23,7 @@ hit ratio hits/sec ttl - + diff --git a/src/views/admin/advanced/jobs.tpl b/src/views/admin/advanced/jobs.tpl new file mode 100644 index 0000000000..8eafcce5cd --- /dev/null +++ b/src/views/admin/advanced/jobs.tpl @@ -0,0 +1,38 @@ + +
    +
    +
    +

    [[admin/advanced/jobs:jobs]]

    +
    +
    + +
    +
    + + + + + + + + + + + + + {{{ each jobs }}} + + + + + + + + + {{{ end }}} + +
    [[admin/advanced/jobs:job-name]][[admin/advanced/jobs:schedule]][[admin/advanced/jobs:next-run]][[admin/advanced/jobs:last-duration]][[admin/advanced/jobs:running]][[admin/advanced/jobs:active]]
    {./name}{./cronTimeHuman} ({./cronTime}){./durationReadable}{{{ if ./running }}}{{{ else }}}{{{ end }}}{{{ if ./active }}}{{{ else }}}{{{ end }}}
    +
    +
    +
    + diff --git a/src/views/admin/appearance/themes.tpl b/src/views/admin/appearance/themes.tpl index 1daa2c24ac..1f01977e0d 100644 --- a/src/views/admin/appearance/themes.tpl +++ b/src/views/admin/appearance/themes.tpl @@ -10,7 +10,11 @@
    - [[admin/appearance/themes:checking-for-installed]] + {{{ if themes.length }}} + + {{{ else }}} +
    [[admin/appearance/themes:no-themes]]
    + {{{ end}}}
    diff --git a/src/views/admin/federation/content.tpl b/src/views/admin/federation/content.tpl index 3ee43fcf21..be584f6de2 100644 --- a/src/views/admin/federation/content.tpl +++ b/src/views/admin/federation/content.tpl @@ -20,6 +20,10 @@ [[admin/settings/activitypub:content.break-string-help]]
    +
    + + +
    diff --git a/src/views/admin/manage/group.tpl b/src/views/admin/manage/group.tpl index f08142547c..775bd5f77f 100644 --- a/src/views/admin/manage/group.tpl +++ b/src/views/admin/manage/group.tpl @@ -44,7 +44,7 @@
    - +
    diff --git a/src/views/admin/partials/navigation.tpl b/src/views/admin/partials/navigation.tpl index 23b6a2c9df..14ceedcbae 100644 --- a/src/views/admin/partials/navigation.tpl +++ b/src/views/admin/partials/navigation.tpl @@ -190,6 +190,7 @@ [[admin/menu:advanced/events]] [[admin/menu:advanced/hooks]] [[admin/menu:advanced/cache]] + [[admin/menu:advanced/jobs]] [[admin/menu:advanced/errors]] [[admin/menu:advanced/logs]] {{{ if env }}} diff --git a/src/views/admin/settings/general.tpl b/src/views/admin/settings/general.tpl index 5dccda3f0a..a5c5289104 100644 --- a/src/views/admin/settings/general.tpl +++ b/src/views/admin/settings/general.tpl @@ -153,6 +153,19 @@ [[admin/settings/general:maskable-icon.help]]

    + +
    + +
    + + + + +
    +

    + [[admin/settings/general:screenshot.help]] +

    +

    diff --git a/src/views/modals/change-picture.tpl b/src/views/modals/change-picture.tpl index f0c16744dc..390f4e95d4 100644 --- a/src/views/modals/change-picture.tpl +++ b/src/views/modals/change-picture.tpl @@ -1,43 +1,39 @@
    -
    - {{{each pictures}}} - - {{{end}}} +
    + {{{ each pictures }}} +
    + + +
    + {{{ end }}}
    -
    +
    +
    [[user:avatar-background-colour]]
    +
    + + {{{ each iconBackgrounds }}} + + {{{ end }}} +
    +
    {{{ if allowProfileImageUploads }}} - {{{ end }}} - - {{{ if uploaded }}} - - {{{ end }}}
    -
    - -
    - -

    [[user:avatar-background-colour]]

    -
    - - {{{ each iconBackgrounds }}} - -{{{ end }}}
    \ No newline at end of file diff --git a/src/views/partials/feed/item.tpl b/src/views/partials/feed/item.tpl index f1d7dbc12c..31cfe758a6 100644 --- a/src/views/partials/feed/item.tpl +++ b/src/views/partials/feed/item.tpl @@ -54,12 +54,12 @@
    -
    +
    {./content}
    -
    - +
    +

    diff --git a/test/activitypub/actors.js b/test/activitypub/actors.js index e659713de3..e185984c1b 100644 --- a/test/activitypub/actors.js +++ b/test/activitypub/actors.js @@ -737,6 +737,10 @@ describe('Pruning', () => { }); describe('Users', () => { + before(async function () { + this.current = await activitypub.actors.prune(); + }); + it('should do nothing if the user is newer than the prune cutoff', async () => { const { id: uid } = helpers.mocks.person(); await activitypub.actors.assert([uid]); @@ -762,7 +766,7 @@ describe('Pruning', () => { assert(result.counts.deleted >= 1); }); - it('should do nothing if the user has some content (e.g. a topic)', async () => { + it('should do nothing if the user has some content (e.g. a topic)', async function () { const { cid } = await categories.create({ name: utils.generateUUID() }); const { id: uid } = helpers.mocks.person(); const { id, note } = helpers.mocks.note({ @@ -776,7 +780,7 @@ describe('Pruning', () => { const result = await activitypub.actors.prune(); assert.strictEqual(result.counts.deleted, 0); - assert.strictEqual(result.counts.preserved, 1); + assert.strictEqual(result.counts.preserved, this.current.counts.preserved + 1); assert.strictEqual(result.counts.missing, 0); }); }); diff --git a/test/activitypub/inbox.js b/test/activitypub/inbox.js new file mode 100644 index 0000000000..4c812a873d --- /dev/null +++ b/test/activitypub/inbox.js @@ -0,0 +1,499 @@ +'use strict'; + +const assert = require('assert'); +const nconf = require('nconf'); + +const db = require('../mocks/databasemock'); +const meta = require('../../src/meta'); +const install = require('../../src/install'); +const user = require('../../src/user'); +const categories = require('../../src/categories'); +const topics = require('../../src/topics'); +const posts = require('../../src/posts'); +const privileges = require('../../src/privileges'); +const activitypub = require('../../src/activitypub'); +const utils = require('../../src/utils'); + +const helpers = require('./helpers'); + +describe('Inbox', () => { + before(async () => { + meta.config.activitypubEnabled = 1; + await install.giveWorldPrivileges(); + }); + + describe('Inbox handling', () => { + describe('helper self-check', () => { + it('should generate a Like activity', () => { + const object = utils.generateUUID(); + const { id: actor } = helpers.mocks.person(); + const { activity } = helpers.mocks.like({ + object, + actor, + }); + + assert.deepStrictEqual(activity, { + '@context': 'https://www.w3.org/ns/activitystreams', + id: `${helpers.mocks._baseUrl}/like/${encodeURIComponent(object)}`, + type: 'Like', + actor, + object, + }); + }); + + it('should generate an Announce activity wrapping a Like activity', () => { + const object = utils.generateUUID(); + const { id: actor } = helpers.mocks.person(); + const { activity: like } = helpers.mocks.like({ + object, + actor, + }); + const { id: gActor } = helpers.mocks.group(); + const { activity } = helpers.mocks.announce({ + actor: gActor, + object: like, + }); + + assert.deepStrictEqual(activity, { + '@context': 'https://www.w3.org/ns/activitystreams', + id: `${helpers.mocks._baseUrl}/announce/${encodeURIComponent(like.id)}`, + type: 'Announce', + to: [ 'https://www.w3.org/ns/activitystreams#Public' ], + cc: [ + `${gActor}/followers`, + ], + actor: gActor, + object: like, + }); + }); + }); + + describe('from a banned account', () => { + before(async function () { + const { id: bannedUid } = helpers.mocks.person(); + this.bannedUid = bannedUid; + + const { note } = helpers.mocks.note({ + attributedTo: bannedUid, + }); + + const uid = await user.create({ username: utils.generateUUID() }); + const { id: boosterUid } = helpers.mocks.person(); + await db.sortedSetAdd(`followersRemote:${boosterUid}`, Date.now(), uid); + const { activity } = helpers.mocks.announce({ + actor: boosterUid, + object: note, + }); + this.activity = activity; + this.pid = note.id; + + await user.bans.ban(bannedUid, 0, 'testing'); + }); + + it('should list the remote user as banned, when queried', async function () { + const isBanned = await user.bans.isBanned(this.bannedUid); + assert.strictEqual(isBanned, true); + }); + + // Can't actually test the middleware because I can't sign a request for a test + + it('should not assert a note if authored by a banned user (boosted by third-party)', async function () { + await activitypub.inbox.announce({ + body: this.activity, + }); + + const exists = await posts.exists(this.pid); + assert.strictEqual(exists, false); + }); + }); + + describe('Create', () => { + let uid; + + before(async () => { + uid = await user.create({ username: utils.generateUUID() }); + }); + + describe('(Note)', () => { + it('should create a new topic in cid -1', async () => { + const { note, id } = helpers.mocks.note(); + const { activity } = helpers.mocks.create(note); + + await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid); + await activitypub.inbox.create({ body: activity }); + + assert(await posts.exists(id)); + + const cid = await posts.getCidByPid(id); + assert.strictEqual(cid, -1); + }); + + it('should not append to the tids_read sorted set', async () => { + const { note, id } = helpers.mocks.note(); + const { activity } = helpers.mocks.create(note); + + await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid); + await activitypub.inbox.create({ body: activity }); + + const exists = await db.exists(`uid:${note.attributedTo}:tids_read`); + assert(!exists); + }); + + it('should create a new topic in a remote category if addressed (category same-origin)', async () => { + const { id: remoteCid } = helpers.mocks.group(); + const { note, id } = helpers.mocks.note({ + audience: [remoteCid], + }); + const { activity } = helpers.mocks.create(note); + + await activitypub.inbox.create({ body: activity }); + + assert(await posts.exists(id)); + + const cid = await posts.getCidByPid(id); + assert.strictEqual(cid, remoteCid); + }); + + it('should create a new topic in cid -1 if a non-same origin remote category is addressed', async function () { + const { id: remoteCid } = helpers.mocks.group({ + id: `https://example.com/${utils.generateUUID()}`, + }); + const { note, id } = helpers.mocks.note({ + audience: [remoteCid], + }); + const { activity } = helpers.mocks.create(note); + try { + await activitypub.inbox.create({ body: activity }); + } catch (err) { + assert(false); + } + + assert(await posts.exists(id)); + const cid = await posts.getCidByPid(id); + assert.strictEqual(cid, -1); + }); + }); + }); + + describe('Announce', () => { + let cid; + + before(async () => { + ({ cid } = await categories.create({ name: utils.generateUUID() })); + }); + + describe('(Create)', () => { + it('should create a new topic in a remote category if addressed', async () => { + const { id: remoteCid } = helpers.mocks.group(); + const { id, note } = helpers.mocks.note({ + audience: [remoteCid], + }); + let { activity } = helpers.mocks.create(note); + ({ activity } = helpers.mocks.announce({ actor: remoteCid, object: activity })); + + await activitypub.inbox.announce({ body: activity }); + + assert(await posts.exists(id)); + + const cid = await posts.getCidByPid(id); + assert.strictEqual(cid, remoteCid); + }); + }); + + describe('(Create) or (Note) referencing local post', () => { + let uid; + let topicData; + let postData; + let localNote; + let announces = 0; + + before(async () => { + uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + ({ topicData, postData } = await topics.post({ + cid, + uid, + title: utils.generateUUID(), + content: utils.generateUUID(), + })); + localNote = await activitypub.mocks.notes.public(postData); + }); + + it('should increment announces counter when a remote user shares', async () => { + const { id } = helpers.mocks.person(); + const { activity } = helpers.mocks.announce({ + actor: id, + object: localNote, + cc: [`${nconf.get('url')}/uid/${topicData.uid}`], + }); + + await activitypub.inbox.announce({ body: activity }); + announces += 1; + + const count = await posts.getPostField(topicData.mainPid, 'announces'); + assert.strictEqual(count, announces); + }); + + it('should contain the remote user announcer id in the post announces zset', async () => { + const { id } = helpers.mocks.person(); + const { activity } = helpers.mocks.announce({ + actor: id, + object: localNote, + cc: [`${nconf.get('url')}/uid/${topicData.uid}`], + }); + + await activitypub.inbox.announce({ body: activity }); + announces += 1; + + const exists = await db.isSortedSetMember(`pid:${topicData.mainPid}:announces`, id); + assert(exists); + }); + + it('should NOT increment announces counter when a remote category shares', async () => { + const { id } = helpers.mocks.group(); + const { activity } = helpers.mocks.announce({ + actor: id, + object: localNote, + cc: [`${nconf.get('url')}/uid/${topicData.uid}`], + }); + + await activitypub.inbox.announce({ body: activity }); + + const count = await posts.getPostField(topicData.mainPid, 'announces'); + assert.strictEqual(count, announces); + }); + + it('should NOT contain the remote category announcer id in the post announces zset', async () => { + const { id } = helpers.mocks.group(); + const { activity } = helpers.mocks.announce({ + actor: id, + object: localNote, + cc: [`${nconf.get('url')}/uid/${topicData.uid}`], + }); + + await activitypub.inbox.announce({ body: activity }); + + const exists = await db.isSortedSetMember(`pid:${topicData.mainPid}:announces`, id); + assert(!exists); + }); + }); + + describe('(Note)', () => { + it('should create a new topic in cid -1 if category not addressed', async () => { + const { note } = helpers.mocks.note(); + await activitypub.actors.assert([note.attributedTo]); + const { activity } = helpers.mocks.announce({ + object: note, + }); + const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + await db.sortedSetAdd(`followersRemote:${activity.actor}`, Date.now(), uid); + + const beforeCount = await db.sortedSetCard(`cid:-1:tids`); + await activitypub.inbox.announce({ body: activity }); + const count = await db.sortedSetCard(`cid:-1:tids`); + + assert.strictEqual(count, beforeCount + 1); + }); + + it('should create a new topic in local category', async () => { + const { note } = helpers.mocks.note({ + cc: [`${nconf.get('url')}/category/${cid}`], + }); + await activitypub.actors.assert([note.attributedTo]); + const { activity } = helpers.mocks.announce({ + object: note, + }); + const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + await db.sortedSetAdd(`followersRemote:${activity.actor}`, Date.now(), uid); + + const beforeCount = await db.sortedSetCard(`cid:${cid}:tids`); + await activitypub.inbox.announce({ body: activity }); + const count = await db.sortedSetCard(`cid:${cid}:tids`); + + assert.strictEqual(count, beforeCount + 1); + }); + }); + + describe('(Like)', () => { + it('should upvote a local post', async () => { + const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + const { postData } = await topics.post({ + cid, + uid, + title: utils.generateUUID(), + content: utils.generateUUID(), + }); + + const { activity: like } = helpers.mocks.like({ + object: `${nconf.get('url')}/post/${postData.pid}`, + }); + const { activity } = helpers.mocks.announce({ + object: like, + }); + + let { upvotes } = await posts.getPostFields(postData.pid, 'upvotes'); + assert.strictEqual(upvotes, 0); + + await activitypub.inbox.announce({ body: activity }); + ({ upvotes } = await posts.getPostFields(postData.pid, 'upvotes')); + assert.strictEqual(upvotes, 1); + }); + + it('should upvote an asserted remote post', async () => { + const { id } = helpers.mocks.note(); + await activitypub.notes.assert(0, id, { skipChecks: true }); + const { activity: like } = helpers.mocks.like({ + object: id, + }); + const { activity } = helpers.mocks.announce({ + object: like, + }); + + let { upvotes } = await posts.getPostFields(id, 'upvotes'); + assert.strictEqual(upvotes, 0); + + await activitypub.inbox.announce({ body: activity }); + + ({ upvotes } = await posts.getPostFields(id, 'upvotes')); + assert.strictEqual(upvotes, 1); + }); + }); + + describe('(Update)', () => { + it('should update a note\'s content', async () => { + const { id: actor } = helpers.mocks.person(); + const { id, note } = helpers.mocks.note({ attributedTo: actor }); + await activitypub.notes.assert(0, id, { skipChecks: true }); + note.content = utils.generateUUID(); + const { activity: update } = helpers.mocks.update({ object: note }); + const { activity } = helpers.mocks.announce({ object: update }); + + await activitypub.inbox.announce({ body: activity }); + + const content = await posts.getPostField(id, 'content'); + assert.strictEqual(content, note.content); + }); + }); + }); + + describe('Like', () => { + before(async function () { + const uid = await user.create({ username: utils.generateUUID() }); + const { cid } = await categories.create({ name: utils.generateUUID() }); + this.cid = cid; + const { postData } = await topics.post({ + uid, + cid, + title: utils.generateUUID(), + content: utils.generateUUID(), + }); + this.postData = postData; + const object = await activitypub.mocks.notes.public(postData); + const { activity } = helpers.mocks.like({ object }); + this.voterUid = activity.actor; + await activitypub.inbox.like({ body: activity }); + }); + + it('should increment a like for the post', async function () { + const voted = await posts.hasVoted(this.postData.pid, this.voterUid); + const count = await posts.getPostField(this.postData.pid, 'upvotes'); + assert(voted); + assert.strictEqual(count, 1); + }); + + it('should not append to the uid upvotes zset', async function () { + const exists = await db.exists(`uid:${this.voterUid}:upvote`); + assert(!exists); + }); + + describe('with privilege revoked (from fediverse pseudo-user)', () => { + before(async function () { + await privileges.categories.rescind(['groups:posts:upvote'], this.cid, 'fediverse'); + const object = await activitypub.mocks.notes.public(this.postData); + const { activity } = helpers.mocks.like({ object }); + this.voterUid = activity.actor; + await activitypub.inbox.like({ body: activity }); + }); + + after(async function () { + await privileges.categories.give(['groups:posts:upvote'], this.cid, 'fediverse'); + }); + + it('should not increment a like for the post', async function () { + const { upvoted } = await posts.hasVoted(this.postData.pid, this.voterUid); + const count = await posts.getPostField(this.postData.pid, 'upvotes'); + assert.strictEqual(upvoted, false); + assert.strictEqual(count, 1); + }); + }); + }); + }); + + describe('Inbox Synchronization', () => { + let cid; + let uid; + let topicData; + + before(async () => { + ({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) })); + }); + + beforeEach(async () => { + uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + ({ topicData } = await topics.post({ + cid, + uid, + title: utils.generateUUID(), + content: utils.generateUUID(), + })); + }); + + it('should add a topic to a user\'s inbox if user is a recipient in OP', async () => { + await db.setAdd(`post:${topicData.mainPid}:recipients`, [uid]); + await activitypub.notes.syncUserInboxes(topicData.tid); + const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); + + assert.strictEqual(inboxed, true); + }); + + it('should add a topic to a user\'s inbox if a user is a recipient in a reply', async () => { + const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); + const { pid } = await topics.reply({ + tid: topicData.tid, + uid, + content: utils.generateUUID(), + }); + await db.setAdd(`post:${pid}:recipients`, [uid]); + await activitypub.notes.syncUserInboxes(topicData.tid); + const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); + + assert.strictEqual(inboxed, true); + }); + + it('should maintain a list of recipients at the topic level', async () => { + await db.setAdd(`post:${topicData.mainPid}:recipients`, [uid]); + await activitypub.notes.syncUserInboxes(topicData.tid); + const [isRecipient, count] = await Promise.all([ + db.isSetMember(`tid:${topicData.tid}:recipients`, uid), + db.setCount(`tid:${topicData.tid}:recipients`), + ]); + + assert(isRecipient); + assert.strictEqual(count, 1); + }); + + it('should add topic to a user\'s inbox if it is explicitly passed in as an argument', async () => { + await activitypub.notes.syncUserInboxes(topicData.tid, uid); + const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); + + assert.strictEqual(inboxed, true); + }); + + it('should remove a topic from a user\'s inbox if that user is no longer a recipient in any contained posts', async () => { + await activitypub.notes.syncUserInboxes(topicData.tid, uid); + await activitypub.notes.syncUserInboxes(topicData.tid); + const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); + + assert.strictEqual(inboxed, false); + }); + }); +}); diff --git a/test/activitypub/notes.js b/test/activitypub/notes.js index 470c7c821c..bded9c322f 100644 --- a/test/activitypub/notes.js +++ b/test/activitypub/notes.js @@ -384,462 +384,6 @@ describe('Notes', () => { }); }); - describe('Inbox handling', () => { - describe('helper self-check', () => { - it('should generate a Like activity', () => { - const object = utils.generateUUID(); - const { id: actor } = helpers.mocks.person(); - const { activity } = helpers.mocks.like({ - object, - actor, - }); - - assert.deepStrictEqual(activity, { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${helpers.mocks._baseUrl}/like/${encodeURIComponent(object)}`, - type: 'Like', - actor, - object, - }); - }); - - it('should generate an Announce activity wrapping a Like activity', () => { - const object = utils.generateUUID(); - const { id: actor } = helpers.mocks.person(); - const { activity: like } = helpers.mocks.like({ - object, - actor, - }); - const { id: gActor } = helpers.mocks.group(); - const { activity } = helpers.mocks.announce({ - actor: gActor, - object: like, - }); - - assert.deepStrictEqual(activity, { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${helpers.mocks._baseUrl}/announce/${encodeURIComponent(like.id)}`, - type: 'Announce', - to: [ 'https://www.w3.org/ns/activitystreams#Public' ], - cc: [ - `${gActor}/followers`, - ], - actor: gActor, - object: like, - }); - }); - }); - - describe('from a banned account', () => { - before(async function () { - const { id: bannedUid } = helpers.mocks.person(); - this.bannedUid = bannedUid; - - const { note } = helpers.mocks.note({ - attributedTo: bannedUid, - }); - - const uid = await user.create({ username: utils.generateUUID() }); - const { id: boosterUid } = helpers.mocks.person(); - await db.sortedSetAdd(`followersRemote:${boosterUid}`, Date.now(), uid); - const { activity } = helpers.mocks.announce({ - actor: boosterUid, - object: note, - }); - this.activity = activity; - this.pid = note.id; - - await user.bans.ban(bannedUid, 0, 'testing'); - }); - - it('should list the remote user as banned, when queried', async function () { - const isBanned = await user.bans.isBanned(this.bannedUid); - assert.strictEqual(isBanned, true); - }); - - // Can't actually test the middleware because I can't sign a request for a test - - it('should not assert a note if authored by a banned user (boosted by third-party)', async function () { - await activitypub.inbox.announce({ - body: this.activity, - }); - - const exists = await posts.exists(this.pid); - assert.strictEqual(exists, false); - }); - }); - - describe('Create', () => { - let uid; - let cid; - - before(async () => { - uid = await user.create({ username: utils.generateUUID() }); - }); - - describe('(Note)', () => { - it('should create a new topic in cid -1', async () => { - const { note, id } = helpers.mocks.note(); - const { activity } = helpers.mocks.create(note); - - await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid); - await activitypub.inbox.create({ body: activity }); - - assert(await posts.exists(id)); - - const cid = await posts.getCidByPid(id); - assert.strictEqual(cid, -1); - }); - - it('should not append to the tids_read sorted set', async () => { - const { note, id } = helpers.mocks.note(); - const { activity } = helpers.mocks.create(note); - - await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid); - await activitypub.inbox.create({ body: activity }); - - const exists = await db.exists(`uid:${note.attributedTo}:tids_read`); - assert(!exists); - }); - - it('should create a new topic in a remote category if addressed (category same-origin)', async () => { - const { id: remoteCid } = helpers.mocks.group(); - const { note, id } = helpers.mocks.note({ - audience: [remoteCid], - }); - const { activity } = helpers.mocks.create(note); - - await activitypub.inbox.create({ body: activity }); - - assert(await posts.exists(id)); - - const cid = await posts.getCidByPid(id); - assert.strictEqual(cid, remoteCid); - }); - - it('should create a new topic in cid -1 if a non-same origin remote category is addressed', async function () { - const { id: remoteCid } = helpers.mocks.group({ - id: `https://example.com/${utils.generateUUID()}`, - }); - const { note, id } = helpers.mocks.note({ - audience: [remoteCid], - }); - const { activity } = helpers.mocks.create(note); - try { - await activitypub.inbox.create({ body: activity }); - } catch (err) { - assert(false); - } - - assert(await posts.exists(id)); - const cid = await posts.getCidByPid(id); - assert.strictEqual(cid, -1); - }); - }); - - describe('(Like)', () => { - let pid; - let voterUid; - - before(async () => { - ({ cid } = await categories.create({ name: utils.generateUUID() })); - const { postData } = await topics.post({ - uid, - cid, - title: utils.generateUUID(), - content: utils.generateUUID(), - }); - pid = postData.pid; - const object = await activitypub.mocks.notes.public(postData); - const { activity } = helpers.mocks.like({ object }); - voterUid = activity.actor; - await activitypub.inbox.like({ body: activity }); - }); - - it('should increment a like for the post', async () => { - const voted = await posts.hasVoted(pid, voterUid); - const count = await posts.getPostField(pid, 'upvotes'); - assert(voted); - assert.strictEqual(count, 1); - }); - - it('should not append to the uid upvotes zset', async () => { - const exists = await db.exists(`uid:${voterUid}:upvote`); - assert(!exists); - }); - }); - }); - - describe('Announce', () => { - let cid; - - before(async () => { - ({ cid } = await categories.create({ name: utils.generateUUID() })); - }); - - describe('(Create)', () => { - it('should create a new topic in a remote category if addressed', async () => { - const { id: remoteCid } = helpers.mocks.group(); - const { id, note } = helpers.mocks.note({ - audience: [remoteCid], - }); - let { activity } = helpers.mocks.create(note); - ({ activity } = helpers.mocks.announce({ actor: remoteCid, object: activity })); - - await activitypub.inbox.announce({ body: activity }); - - assert(await posts.exists(id)); - - const cid = await posts.getCidByPid(id); - assert.strictEqual(cid, remoteCid); - }); - }); - - describe('(Create) or (Note) referencing local post', () => { - let uid; - let topicData; - let postData; - let localNote; - let announces = 0; - - before(async () => { - uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - ({ topicData, postData } = await topics.post({ - cid, - uid, - title: utils.generateUUID(), - content: utils.generateUUID(), - })); - localNote = await activitypub.mocks.notes.public(postData); - }); - - it('should increment announces counter when a remote user shares', async () => { - const { id } = helpers.mocks.person(); - const { activity } = helpers.mocks.announce({ - actor: id, - object: localNote, - cc: [`${nconf.get('url')}/uid/${topicData.uid}`], - }); - - await activitypub.inbox.announce({ body: activity }); - announces += 1; - - const count = await posts.getPostField(topicData.mainPid, 'announces'); - assert.strictEqual(count, announces); - }); - - it('should contain the remote user announcer id in the post announces zset', async () => { - const { id } = helpers.mocks.person(); - const { activity } = helpers.mocks.announce({ - actor: id, - object: localNote, - cc: [`${nconf.get('url')}/uid/${topicData.uid}`], - }); - - await activitypub.inbox.announce({ body: activity }); - announces += 1; - - const exists = await db.isSortedSetMember(`pid:${topicData.mainPid}:announces`, id); - assert(exists); - }); - - it('should NOT increment announces counter when a remote category shares', async () => { - const { id } = helpers.mocks.group(); - const { activity } = helpers.mocks.announce({ - actor: id, - object: localNote, - cc: [`${nconf.get('url')}/uid/${topicData.uid}`], - }); - - await activitypub.inbox.announce({ body: activity }); - - const count = await posts.getPostField(topicData.mainPid, 'announces'); - assert.strictEqual(count, announces); - }); - - it('should NOT contain the remote category announcer id in the post announces zset', async () => { - const { id } = helpers.mocks.group(); - const { activity } = helpers.mocks.announce({ - actor: id, - object: localNote, - cc: [`${nconf.get('url')}/uid/${topicData.uid}`], - }); - - await activitypub.inbox.announce({ body: activity }); - - const exists = await db.isSortedSetMember(`pid:${topicData.mainPid}:announces`, id); - assert(!exists); - }); - }); - - describe('(Note)', () => { - it('should create a new topic in cid -1 if category not addressed', async () => { - const { note } = helpers.mocks.note(); - await activitypub.actors.assert([note.attributedTo]); - const { activity } = helpers.mocks.announce({ - object: note, - }); - const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - await db.sortedSetAdd(`followersRemote:${activity.actor}`, Date.now(), uid); - - const beforeCount = await db.sortedSetCard(`cid:-1:tids`); - await activitypub.inbox.announce({ body: activity }); - const count = await db.sortedSetCard(`cid:-1:tids`); - - assert.strictEqual(count, beforeCount + 1); - }); - - it('should create a new topic in local category', async () => { - const { note } = helpers.mocks.note({ - cc: [`${nconf.get('url')}/category/${cid}`], - }); - await activitypub.actors.assert([note.attributedTo]); - const { activity } = helpers.mocks.announce({ - object: note, - }); - const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - await db.sortedSetAdd(`followersRemote:${activity.actor}`, Date.now(), uid); - - const beforeCount = await db.sortedSetCard(`cid:${cid}:tids`); - await activitypub.inbox.announce({ body: activity }); - const count = await db.sortedSetCard(`cid:${cid}:tids`); - - assert.strictEqual(count, beforeCount + 1); - }); - }); - - describe('(Like)', () => { - it('should upvote a local post', async () => { - const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - const { postData } = await topics.post({ - cid, - uid, - title: utils.generateUUID(), - content: utils.generateUUID(), - }); - - const { activity: like } = helpers.mocks.like({ - object: `${nconf.get('url')}/post/${postData.pid}`, - }); - const { activity } = helpers.mocks.announce({ - object: like, - }); - - let { upvotes } = await posts.getPostFields(postData.pid, 'upvotes'); - assert.strictEqual(upvotes, 0); - - await activitypub.inbox.announce({ body: activity }); - ({ upvotes } = await posts.getPostFields(postData.pid, 'upvotes')); - assert.strictEqual(upvotes, 1); - }); - - it('should upvote an asserted remote post', async () => { - const { id } = helpers.mocks.note(); - await activitypub.notes.assert(0, id, { skipChecks: true }); - const { activity: like } = helpers.mocks.like({ - object: id, - }); - const { activity } = helpers.mocks.announce({ - object: like, - }); - - let { upvotes } = await posts.getPostFields(id, 'upvotes'); - assert.strictEqual(upvotes, 0); - - await activitypub.inbox.announce({ body: activity }); - - ({ upvotes } = await posts.getPostFields(id, 'upvotes')); - assert.strictEqual(upvotes, 1); - }); - }); - - describe('(Update)', () => { - it('should update a note\'s content', async () => { - const { id: actor } = helpers.mocks.person(); - const { id, note } = helpers.mocks.note({ attributedTo: actor }); - await activitypub.notes.assert(0, id, { skipChecks: true }); - note.content = utils.generateUUID(); - const { activity: update } = helpers.mocks.update({ object: note }); - const { activity } = helpers.mocks.announce({ object: update }); - - await activitypub.inbox.announce({ body: activity }); - - const content = await posts.getPostField(id, 'content'); - assert.strictEqual(content, note.content); - }); - }); - }); - }); - - describe('Inbox Synchronization', () => { - let cid; - let uid; - let topicData; - - before(async () => { - ({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) })); - }); - - beforeEach(async () => { - uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - ({ topicData } = await topics.post({ - cid, - uid, - title: utils.generateUUID(), - content: utils.generateUUID(), - })); - }); - - it('should add a topic to a user\'s inbox if user is a recipient in OP', async () => { - await db.setAdd(`post:${topicData.mainPid}:recipients`, [uid]); - await activitypub.notes.syncUserInboxes(topicData.tid); - const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); - - assert.strictEqual(inboxed, true); - }); - - it('should add a topic to a user\'s inbox if a user is a recipient in a reply', async () => { - const uid = await user.create({ username: utils.generateUUID().slice(0, 10) }); - const { pid } = await topics.reply({ - tid: topicData.tid, - uid, - content: utils.generateUUID(), - }); - await db.setAdd(`post:${pid}:recipients`, [uid]); - await activitypub.notes.syncUserInboxes(topicData.tid); - const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); - - assert.strictEqual(inboxed, true); - }); - - it('should maintain a list of recipients at the topic level', async () => { - await db.setAdd(`post:${topicData.mainPid}:recipients`, [uid]); - await activitypub.notes.syncUserInboxes(topicData.tid); - const [isRecipient, count] = await Promise.all([ - db.isSetMember(`tid:${topicData.tid}:recipients`, uid), - db.setCount(`tid:${topicData.tid}:recipients`), - ]); - - assert(isRecipient); - assert.strictEqual(count, 1); - }); - - it('should add topic to a user\'s inbox if it is explicitly passed in as an argument', async () => { - await activitypub.notes.syncUserInboxes(topicData.tid, uid); - const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); - - assert.strictEqual(inboxed, true); - }); - - it('should remove a topic from a user\'s inbox if that user is no longer a recipient in any contained posts', async () => { - await activitypub.notes.syncUserInboxes(topicData.tid, uid); - await activitypub.notes.syncUserInboxes(topicData.tid); - const inboxed = await db.isSortedSetMember(`uid:${uid}:inbox`, topicData.tid); - - assert.strictEqual(inboxed, false); - }); - }); - describe('Deletion', () => { let cid; let uid; diff --git a/test/activitypub/signatures.js b/test/activitypub/signatures.js index c05b24140b..22353d503d 100644 --- a/test/activitypub/signatures.js +++ b/test/activitypub/signatures.js @@ -35,7 +35,7 @@ describe('http signature signing and verification', () => { assert(signature); assert(dateObj); - assert.strictEqual(digest, null); + assert.strictEqual(digest, undefined); }); it('should also return a digest hash if payload is passed in', async () => { diff --git a/test/controllers-admin.js b/test/controllers-admin.js index 154fec69a8..c7498eefee 100644 --- a/test/controllers-admin.js +++ b/test/controllers-admin.js @@ -629,6 +629,7 @@ describe('Admin Controllers', () => { 'uploadfavicon', 'uploadTouchIcon', 'uploadMaskableIcon', + 'uploadScreenshot', 'uploadlogo', 'uploadOgImage', 'uploadDefaultAvatar', @@ -643,7 +644,7 @@ describe('Admin Controllers', () => { await privileges.admin.give([privileges.admin.routeMap[route]], uid); ({ response: res } = await request.get(`${nconf.get('url')}/api/admin/${route}`, requestOpts)); - assert.strictEqual(res.statusCode, 200); + assert.strictEqual(res.statusCode, 200, `${route} returned ${res.statusCode} instead of 200`); await privileges.admin.rescind([privileges.admin.routeMap[route]], uid); } diff --git a/test/database/sorted.js b/test/database/sorted.js index a375b2ec48..fde2bafb0b 100644 --- a/test/database/sorted.js +++ b/test/database/sorted.js @@ -93,6 +93,22 @@ NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:rea }); assert.strictEqual(data.length, 0); }); + + it('should handle floating point scores', async () => { + await db.sortedSetAdd('scanzset6', [1.5, 2.5, 3.5, 4.5, 5.5, 6.5], ['aaab{', 'bbbb', 'bbcb', 'ddb', 'dddd', 'adb']); + const data = await db.getSortedSetScan({ + key: 'scanzset6', + match: '*b', + withScores: true, + }); + data.sort((a, b) => b.score - a.score); + assert.deepStrictEqual(data, [ + { value: 'adb', score: 6.5 }, + { value: 'ddb', score: 4.5 }, + { value: 'bbcb', score: 3.5 }, + { value: 'bbbb', score: 2.5 }, + ]); + }); }); describe('sortedSetAdd()', () => { diff --git a/test/notifications.js b/test/notifications.js index 33d03fadcf..9596fd8112 100644 --- a/test/notifications.js +++ b/test/notifications.js @@ -75,7 +75,8 @@ describe('Notifications', () => { const notifData = await notifications.get(nid); assert.strictEqual(notifData.icon, undefined); assert.strictEqual(notifData.user['icon:text'], 'I'); - assert.strictEqual(notifData.user['icon:bgColor'], '#3f51b5'); + assert(notifData.user['icon:bgColor'].length === 7 && + notifData.user['icon:bgColor'].startsWith('#')); }); it('should return null if pid is same and importance is lower', (done) => { diff --git a/test/posts.js b/test/posts.js index 601774cd9e..9ca3809fa8 100644 --- a/test/posts.js +++ b/test/posts.js @@ -384,7 +384,10 @@ describe('Post\'s', () => { let pid; let replyPid; let tid; - before((done) => { + before(function (done) { + this.minimumTitleLength = meta.config.minimumTitleLength; + meta.config.minimumTitleLength = 3; + topics.post({ uid: voterUid, cid: cid, @@ -408,6 +411,10 @@ describe('Post\'s', () => { }); }); + after(function () { + meta.config.minimumTitleLength = this.minimumTitleLength; + }); + it('should error if user is not logged in', async () => { try { await apiPosts.edit({ uid: 0 }, { pid: pid, content: 'gg' }); diff --git a/test/socket.io.js b/test/socket.io.js index 2ef06eef4f..45ffb43dd8 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -84,19 +84,6 @@ describe('socket.io', () => { }); }); - it('should get installed themes', (done) => { - const themes = ['nodebb-theme-persona']; - io.emit('admin.themes.getInstalled', (err, data) => { - assert.ifError(err); - assert(data); - const installed = data.map(theme => theme.id); - themes.forEach((theme) => { - assert(installed.includes(theme)); - }); - done(); - }); - }); - it('should ban a user', async () => { const apiUser = require('../src/api/users'); await apiUser.ban({ uid: adminUid }, { uid: regularUid, reason: 'spammer' }); diff --git a/test/topics.js b/test/topics.js index 21ecffd245..f67e0fc40e 100644 --- a/test/topics.js +++ b/test/topics.js @@ -1423,7 +1423,13 @@ describe('Topic\'s', () => { const result = await topics.post({ uid: adminUid, title: 'deleted unread', content: 'not unread', cid: categoryObj.cid }); await topics.delete(result.topicData.tid, adminUid); const unreadTids = await topics.getUnreadTids({ cid: 0, uid: uid }); - assert(!unreadTids.includes(result.topicData.tid), JSON.stringify({ unreadTids, tid: result.topicData.tid })); + + await sleep(2000); + const _unreadTids = await topics.getUnreadTids({ cid: 0, uid: uid }); + assert( + !unreadTids.includes(result.topicData.tid), + JSON.stringify({ unreadTids, _unreadTids, tid: result.topicData.tid }) + ); }); }); @@ -1632,15 +1638,20 @@ describe('Topic\'s', () => { assert.deepStrictEqual(tags, ['deleteme1', 'deleteme3']); }); - it('should delete tag', (done) => { - topics.deleteTag('javascript', (err) => { - assert.ifError(err); - db.getObject('tag:javascript', (err, data) => { - assert.ifError(err); - assert(!data); - done(); - }); - }); + it('should delete tag', async () => { + await topics.deleteTag('javascript'); + const data = await db.getObject('tag:javascript'); + assert(!data); + }); + + it('should properly remove tags from topic hash when removing all tags of a topic', async () => { + const result1 = await topics.post({ uid: adminUid, tags: ['tag1', 'tag2', 'tag3', 'tag4', 'tag5'], title: 'many tags much wow', content: 'topic 1 content', cid: topic.categoryId }); + const result2 = await topics.post({ uid: adminUid, tags: ['best1', 'tag2', 'best2', 'tag3', 'best3'], title: 'many tags much wow', content: 'topic 1 content', cid: topic.categoryId }); + await topics.deleteTags(['tag1', 'tag2', 'tag3', 'tag4', 'tag5']); + const topicData1 = await topics.getTopicData(result1.topicData.tid); + const topicData2 = await topics.getTopicData(result2.topicData.tid); + assert.deepStrictEqual(topicData1.tags.map(t => t.value), []); + assert.deepStrictEqual(topicData2.tags.map(t => t.value), ['best1', 'best2', 'best3']); }); it('should delete category tag as well', async () => { diff --git a/test/user.js b/test/user.js index f35720e217..3eb85d83ed 100644 --- a/test/user.js +++ b/test/user.js @@ -483,24 +483,11 @@ describe('User', () => { }); describe('.delete()', () => { - let uid; - before((done) => { - User.create({ username: 'usertodelete', password: '123456', email: 'delete@me.com' }, (err, newUid) => { - assert.ifError(err); - uid = newUid; - done(); - }); - }); - - it('should delete a user account', (done) => { - User.delete(1, uid, (err) => { - assert.ifError(err); - User.existsBySlug('usertodelete', (err, exists) => { - assert.ifError(err); - assert.equal(exists, false); - done(); - }); - }); + it('should delete a user account', async () => { + const uid = await User.create({ username: 'usertodelete', password: '123456', email: 'delete@me.com' }); + await User.delete(1, uid); + const exists = await User.existsBySlug('usertodelete'); + assert.strictEqual(exists, false); }); it('should not re-add user to users:postcount if post is purged after user account deletion', async () => { @@ -538,7 +525,6 @@ describe('User', () => { }); it('should delete user even if they started a chat', async () => { - const socketModules = require('../src/socket.io/modules'); const uid1 = await User.create({ username: 'chatuserdelete1' }); const uid2 = await User.create({ username: 'chatuserdelete2' }); const roomId = await messaging.newRoom(uid1, { uids: [uid2] }); @@ -1042,7 +1028,8 @@ describe('User', () => { it('should set user picture to uploaded', async () => { await User.setUserField(uid, 'uploadedpicture', '/test'); - await apiUser.changePicture({ uid: uid }, { type: 'uploaded', uid: uid }); + await db.sortedSetAdd(`uid:${uid}:profile:pictures`, Date.now(), '/test'); + await apiUser.changePicture({ uid: uid }, { type: 'uploaded', picture: '/test', uid: uid }); const picture = await User.getUserField(uid, 'picture'); assert.equal(picture, `${nconf.get('relative_path')}/test`); }); @@ -2297,14 +2284,12 @@ describe('User', () => { }); describe('user jobs', () => { - it('should start user jobs', (done) => { - User.startJobs(); - done(); + it('should start user jobs', async () => { + await User.startJobs(); }); - it('should stop user jobs', (done) => { + it('should stop user jobs', async () => { User.stopJobs(); - done(); }); it('should send digest', (done) => {