mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-17 05:50:25 +01:00
Compare commits
7 Commits
socket-not
...
v1.15.3-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a526fd860b | ||
|
|
05a50abdd4 | ||
|
|
79696abfd1 | ||
|
|
8b7b6d5e82 | ||
|
|
075f57e728 | ||
|
|
de0a7dccea | ||
|
|
69b1ab7009 |
@@ -10,21 +10,13 @@ checks:
|
||||
threshold: 500
|
||||
method-lines:
|
||||
config:
|
||||
threshold: 75
|
||||
threshold: 50
|
||||
method-complexity:
|
||||
config:
|
||||
threshold: 10
|
||||
similar-code:
|
||||
config:
|
||||
threshold: 65
|
||||
plugins:
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
javascript:
|
||||
mass_threshold: 110
|
||||
count_threshold: 3
|
||||
exclude_paths:
|
||||
- "public/vendor/*"
|
||||
- "test/*"
|
||||
@@ -1,10 +0,0 @@
|
||||
.*
|
||||
logs
|
||||
test
|
||||
node_modules
|
||||
commitlint.config.js
|
||||
nodebb.bat
|
||||
renovate.json
|
||||
*.yml
|
||||
*.md
|
||||
Dockerfile
|
||||
@@ -18,4 +18,3 @@ logs/
|
||||
.eslintrc
|
||||
test/files
|
||||
*.min.js
|
||||
install/docker/
|
||||
139
.eslintrc
139
.eslintrc
@@ -1,3 +1,140 @@
|
||||
{
|
||||
"extends": "nodebb"
|
||||
"extends": "airbnb-base",
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// Customized
|
||||
"handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ],
|
||||
"comma-dangle": ["error", {
|
||||
"arrays": "always-multiline",
|
||||
"objects": "always-multiline",
|
||||
"imports": "always-multiline",
|
||||
"exports": "always-multiline",
|
||||
"functions": "never"
|
||||
}],
|
||||
"no-return-await": "off",
|
||||
"no-constant-condition": "off",
|
||||
"no-empty": ["error", { "allowEmptyCatch": true }],
|
||||
"no-underscore-dangle": "off",
|
||||
"no-console": "off",
|
||||
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
|
||||
"strict": ["error", "global"],
|
||||
"consistent-return": "off",
|
||||
"func-names": "off",
|
||||
"no-tabs": "off",
|
||||
"indent": ["error", "tab", { "SwitchCase": 1 }],
|
||||
"no-eq-null": "off",
|
||||
"camelcase": "off",
|
||||
"no-new": "off",
|
||||
"no-shadow": "off",
|
||||
"no-use-before-define": ["error", "nofunc"],
|
||||
"no-prototype-builtins": "off",
|
||||
"new-cap": "off",
|
||||
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
|
||||
"object-curly-newline": "off",
|
||||
"no-restricted-globals": "off",
|
||||
"function-paren-newline": "off",
|
||||
"import/no-unresolved": "error",
|
||||
"quotes": ["error", "single", {
|
||||
"avoidEscape": true,
|
||||
"allowTemplateLiterals": true
|
||||
}],
|
||||
"no-else-return": [ "error", { "allowElseIf": true } ],
|
||||
"operator-linebreak": [ "error", "after" ],
|
||||
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
||||
|
||||
// ES6
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
"prefer-template": "off",
|
||||
"no-var": "off",
|
||||
"object-shorthand": "off",
|
||||
"vars-on-top": "off",
|
||||
"prefer-destructuring": "off",
|
||||
|
||||
// TODO
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"import/no-dynamic-require": "off",
|
||||
"import/newline-after-import": "off",
|
||||
"no-bitwise": "off",
|
||||
"global-require": "off",
|
||||
"max-len": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"no-script-url": "off",
|
||||
"default-case": "off",
|
||||
"linebreak-style": "off",
|
||||
|
||||
// "no-multi-assign": "off",
|
||||
// "one-var": "off",
|
||||
// "no-undef": "off",
|
||||
// "max-nested-callbacks": "off",
|
||||
// "no-mixed-requires": "off",
|
||||
// "brace-style": "off",
|
||||
// "max-statements-per-line": "off",
|
||||
// "no-unused-vars": "off",
|
||||
// "no-mixed-spaces-and-tabs": "off",
|
||||
// "no-useless-concat": "off",
|
||||
// "require-jsdoc": "off",
|
||||
// "eqeqeq": "off",
|
||||
// "no-negated-condition": "off",
|
||||
// "one-var-declaration-per-line": "off",
|
||||
// "no-lonely-if": "off",
|
||||
// "radix": "off",
|
||||
// "no-else-return": "off",
|
||||
// "no-useless-escape": "off",
|
||||
// "block-scoped-var": "off",
|
||||
// "operator-assignment": "off",
|
||||
// "yoda": "off",
|
||||
// "no-loop-func": "off",
|
||||
// "no-void": "off",
|
||||
// "valid-jsdoc": "off",
|
||||
// "no-cond-assign": "off",
|
||||
// "no-redeclare": "off",
|
||||
// "no-unreachable": "off",
|
||||
// "no-nested-ternary": "off",
|
||||
// "operator-linebreak": "off",
|
||||
// "guard-for-in": "off",
|
||||
// "no-unneeded-ternary": "off",
|
||||
// "no-sequences": "off",
|
||||
// "no-extend-native": "off",
|
||||
// "no-shadow-restricted-names": "off",
|
||||
// "no-extra-boolean-cast": "off",
|
||||
// "no-path-concat": "off",
|
||||
// "no-unused-expressions": "off",
|
||||
// "no-return-assign": "off",
|
||||
// "no-restricted-modules": "off",
|
||||
// "object-curly-spacing": "off",
|
||||
// "indent": "off",
|
||||
// "padded-blocks": "off",
|
||||
// "eol-last": "off",
|
||||
// "lines-around-directive": "off",
|
||||
// "strict": "off",
|
||||
// "comma-dangle": "off",
|
||||
// "no-multi-spaces": "off",
|
||||
// "quotes": "off",
|
||||
// "keyword-spacing": "off",
|
||||
// "no-mixed-operators": "off",
|
||||
// "comma-spacing": "off",
|
||||
// "no-trailing-spaces": "off",
|
||||
// "key-spacing": "off",
|
||||
"no-multiple-empty-lines": "off"
|
||||
// "spaced-comment": "off",
|
||||
// "space-in-parens": "off",
|
||||
// "block-spacing": "off",
|
||||
// "quote-props": "off",
|
||||
// "space-unary-ops": "off",
|
||||
// "no-empty": "off",
|
||||
// "dot-notation": "off",
|
||||
// "func-call-spacing": "off",
|
||||
// "array-bracket-spacing": "off",
|
||||
// "object-property-newline": "off",
|
||||
// "no-continue": "off",
|
||||
// "no-extra-semi": "off",
|
||||
// "no-spaced-func": "off",
|
||||
// "no-useless-return": "off"
|
||||
}
|
||||
}
|
||||
|
||||
29
.github/ISSUE_TEMPLATE.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<!--
|
||||
== Github Issues are for bug reports and feature requests only ==
|
||||
== Please visit https://community.nodebb.org for other support ==
|
||||
== Found a security exploit? Please email us at security@nodebb.org instead for immediate attention ==
|
||||
== → DO NOT SUBMIT VULNERABILITIES TO THE PUBLIC BUG TRACKER ==
|
||||
-->
|
||||
|
||||
<!-- ++ Please include the following information when submitting a bug report ++ -->
|
||||
|
||||
- **NodeBB version:**
|
||||
- **NodeBB git hash:**
|
||||
- **NodeJS version:**
|
||||
<!-- (to find your git hash, execute `git rev-parse HEAD` from the main NodeBB directory) -->
|
||||
- **Installed NodeBB Plugins:**
|
||||
<!-- (to find installed plugins run ./nodebb plugins) -->
|
||||
- **Database type:** mongo, redis, or postgres
|
||||
- **Database version:**
|
||||
<!-- `mongod --version`, `redis-server --version`, or `postgres --version` -->
|
||||
- **Exact steps to cause this issue:**
|
||||
<!--
|
||||
1. First I did this...
|
||||
2. Then, I clicked on this item...
|
||||
-->
|
||||
- **What you expected:**
|
||||
<!-- e.g. I expected *abc* to *xyz* -->
|
||||
- **What happened instead:**
|
||||
<!-- e.g. Instead, I got *zyx* and NodeBB set fire to my house -->
|
||||
|
||||
<!-- Thank you! -->
|
||||
81
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
81
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -1,81 +0,0 @@
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Github Issues are for bug reports and feature requests only
|
||||
Please visit https://community.nodebb.org for other support
|
||||
Found a security exploit? Please email us at security@nodebb.org instead for immediate attention
|
||||
### → DO NOT SUBMIT VULNERABILITIES TO THE PUBLIC BUG TRACKER ←
|
||||
- type: input
|
||||
attributes:
|
||||
label: NodeBB version
|
||||
placeholder: e.g. v2.2.0
|
||||
- type: input
|
||||
attributes:
|
||||
label: NodeBB git hash
|
||||
description: to find your git hash, execute `git rev-parse HEAD` from the main NodeBB directory
|
||||
placeholder: e.g. 783250ee6f8c51cdc243ce3b8d9f1a080517247e
|
||||
- type: input
|
||||
attributes:
|
||||
label: NodeJS version
|
||||
placeholder: e.g. v16.15.1
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Installed NodeBB plugins
|
||||
description: to find installed plugins run `./nodebb plugins`
|
||||
placeholder: |
|
||||
e.g.
|
||||
* nodebb-plugin-2factor@5.0.1 (installed, disabled)
|
||||
* nodebb-plugin-composer-default@8.0.0 (installed, enabled)
|
||||
* nodebb-plugin-dbsearch@5.1.5 (installed, disabled)
|
||||
* nodebb-plugin-emoji@4.0.4 (installed, enabled)
|
||||
* nodebb-plugin-emoji-android@3.0.0 (installed, enabled)
|
||||
* nodebb-plugin-markdown@10.0.0 (installed, enabled)
|
||||
* nodebb-plugin-mentions@3.0.11 (installed, enabled)
|
||||
* nodebb-plugin-spam-be-gone@1.0.0 (installed, disabled)
|
||||
* nodebb-rewards-essentials@0.2.1 (installed, enabled)
|
||||
* nodebb-theme-lavender@6.0.0 (installed, disabled)
|
||||
* nodebb-theme-persona@12.0.11 (installed, enabled)
|
||||
* nodebb-theme-slick@2.0.2 (installed, disabled)
|
||||
* nodebb-theme-vanilla@12.1.18 (installed, disabled)
|
||||
* nodebb-widget-essentials@6.0.0 (installed, enabled)
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Database type
|
||||
multiple: true
|
||||
options:
|
||||
- MongoDB
|
||||
- Redis
|
||||
- PostgreSQL
|
||||
- type: input
|
||||
attributes:
|
||||
label: Database version
|
||||
description: "`mongod --version`, `redis-server --version`, or `postgres --version`"
|
||||
placeholder: e.g. v5.0.9
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Exact steps to cause this issue
|
||||
placeholder: |
|
||||
1. First I did this...
|
||||
2. Then, I clicked on this item...
|
||||
|
||||
A quick note: MP4 and MOV formatted video files are now allowed to be uploaded to GH.
|
||||
Please upload if reproduction steps are hard to describe or reproduce reliably.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What you expected
|
||||
placeholder: e.g. I expected *abc* to *xyz*
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What happened instead
|
||||
placeholder: e.g. Instead, I got *zyx* and NodeBB set fire to my house
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: Any additional context about the issue you're encountering
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "**Thank you!**"
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Community Forum
|
||||
url: https://community.nodebb.org
|
||||
about: Github Issues are for bug reports and feature requests only, please use community forum for other support
|
||||
24
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
24
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Github Issues are for bug reports and feature requests only
|
||||
Please visit https://community.nodebb.org for other support
|
||||
Found a security exploit? Please email us at security@nodebb.org instead for immediate attention
|
||||
### → DO NOT SUBMIT VULNERABILITIES TO THE PUBLIC BUG TRACKER ←
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Community forum reference
|
||||
description: If this feature was already discussed on the Community Forum link it here
|
||||
placeholder: https://community.nodebb.org/topic/0/example-feature-request
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "**Thank you!**"
|
||||
4
.github/SECURITY.md
vendored
4
.github/SECURITY.md
vendored
@@ -2,8 +2,8 @@
|
||||
|
||||
NodeBB's security policy is based around a private bug bounty program. Users are invited to explore NodeBB for vulnerabilities, and report them to the NodeBB team so that they can be patched.
|
||||
|
||||
If you have found a security vulnerability, **do not post it onto our GitHub tracker**. Some security vulnerabilities are quite severe and discretion is recommended. Email the NodeBB Security Team at security@nodebb.org, instead, even if you are not sure whether something qualifies.
|
||||
If you have found a security vulnerability, **do not post it onto our GitHub tracker**. Some security vulnerabilities are quite severe and discretion is recommended. Email the NodeBB Security Team at security@nodebb.org, instead.
|
||||
|
||||
# Bug Bounty Program
|
||||
|
||||
Security vulnerability reports may be eligible for a bounty based on severity and confirmation from NodeBB team members. For full details regarding our bug bounty program, including the bounty amounts, please consult the [dedicated page for our Bug Bounty Program](https://nodebb.org/bounty).
|
||||
Security vulnerability reports may be eligible for a bounty based on severity and confirmation from NodeBB team members. For full details regarding our bug bounty program, including the bounty amounts, please consult the following page: https://blog.nodebb.org/bounty
|
||||
61
.github/workflows/docker.yml
vendored
61
.github/workflows/docker.yml
vendored
@@ -1,61 +0,0 @@
|
||||
name: Run Docker
|
||||
|
||||
# Controls when the workflow will run
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'v*.x'
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}.x
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=ref,event=branch,enable=${{ github.event.repository.default_branch != github.ref }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
30
.github/workflows/test.yaml
vendored
30
.github/workflows/test.yaml
vendored
@@ -14,32 +14,26 @@ defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
permissions:
|
||||
checks: write # for coverallsapp/github-action to create new checks
|
||||
contents: read # for actions/checkout to fetch code
|
||||
name: Lint and test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node: [18, 20]
|
||||
node: [10, 12, 14]
|
||||
database: [mongo-dev, mongo, redis, postgres]
|
||||
include:
|
||||
# only run coverage once
|
||||
- os: ubuntu-latest
|
||||
node: 18
|
||||
node: 14
|
||||
coverage: true
|
||||
# test under development once
|
||||
- database: mongo-dev
|
||||
test_env: development
|
||||
# only run eslint once
|
||||
- os: ubuntu-latest
|
||||
node: 18
|
||||
node: 14
|
||||
database: mongo-dev
|
||||
lint: true
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -48,7 +42,7 @@ jobs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: 'postgres:16-alpine'
|
||||
image: 'postgres:10-alpine'
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -63,7 +57,7 @@ jobs:
|
||||
- 5432:5432
|
||||
|
||||
redis:
|
||||
image: 'redis:7.2.3'
|
||||
image: 'redis:2.8.9'
|
||||
# Set health checks to wait until redis has started
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
@@ -75,18 +69,18 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
mongo:
|
||||
image: 'mongo:7.0'
|
||||
image: 'mongo:3.2'
|
||||
ports:
|
||||
# Maps port 27017 on service container to the host
|
||||
- 27017:27017
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: cp install/package.json package.json
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
@@ -192,21 +186,19 @@ jobs:
|
||||
run: npm run coverage
|
||||
|
||||
- name: Test coverage
|
||||
uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # v2.2.3
|
||||
uses: coverallsapp/github-action@v1.1.2
|
||||
if: matrix.coverage
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
flag-name: ${{ matrix.os }}-node-${{ matrix.node }}-db-${{ matrix.database }}
|
||||
parallel: true
|
||||
|
||||
|
||||
finish:
|
||||
permissions:
|
||||
checks: write # for coverallsapp/github-action to create new checks
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Coveralls Finished
|
||||
uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # v2.2.3
|
||||
uses: coverallsapp/github-action@v1.1.2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
parallel-finished: true
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -68,7 +68,4 @@ test/files/normalise-resized.jpg
|
||||
package-lock.json
|
||||
/package.json
|
||||
*.mongodb
|
||||
link-plugins.sh
|
||||
test.sh
|
||||
|
||||
.docker/
|
||||
link-plugins.sh
|
||||
1
.husky/.gitignore
vendored
1
.husky/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
_
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install commitlint --edit $1
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install lint-staged
|
||||
17
.jsbeautifyrc
Normal file
17
.jsbeautifyrc
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"indent_size": 4,
|
||||
"indent_char": " ",
|
||||
"indent_level": 0,
|
||||
"indent_with_tabs": true,
|
||||
"preserve_newlines": true,
|
||||
"max_preserve_newlines": 10,
|
||||
"jslint_happy": true,
|
||||
"brace_style": "collapse",
|
||||
"keep_array_indentation": false,
|
||||
"keep_function_indentation": false,
|
||||
"space_before_conditional": true,
|
||||
"break_chained_methods": false,
|
||||
"eval_code": false,
|
||||
"unescape_strings": false,
|
||||
"wrap_line_length": 0
|
||||
}
|
||||
91
.jshintrc
Normal file
91
.jshintrc
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
// JSHint Default Configuration File (as on JSHint website)
|
||||
// See http://jshint.com/docs/ for more details
|
||||
|
||||
"maxerr" : 50, // {int} Maximum error before stopping
|
||||
|
||||
"esversion": 6,
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"indent" : 4, // {int} Number of spaces to use for indentation
|
||||
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : false, // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : true, // true: Require all defined variables be used
|
||||
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||
"trailing" : false, // true: Prohibit trailing whitespaces
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : false, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||
// (ex: `for each`, multiple try/catch, function expression…)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
// Environments
|
||||
"browser" : true, // Web Browser (window, document, etc)
|
||||
"couch" : false, // CouchDB
|
||||
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||
"dojo" : false, // Dojo Toolkit
|
||||
"jquery" : true, // jQuery
|
||||
"mootools" : false, // MooTools
|
||||
"node" : true, // Node.js
|
||||
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||
"prototypejs" : false, // Prototype and Scriptaculous
|
||||
"rhino" : false, // Rhino
|
||||
"worker" : false, // Web Workers
|
||||
"wsh" : false, // Windows Scripting Host
|
||||
"yui" : false, // Yahoo User Interface
|
||||
"mocha": true,
|
||||
|
||||
// Legacy
|
||||
"nomen" : false, // true: Prohibit dangling `_` in variables
|
||||
"onevar" : false, // true: Allow only one `var` statement per function
|
||||
"passfail" : false, // true: Stop on first error
|
||||
"white" : false, // true: Check against strict whitespace and indentation rules
|
||||
|
||||
// Custom Globals
|
||||
"globals" : {
|
||||
"Promise": true
|
||||
} // additional predefined global variables
|
||||
}
|
||||
7474
.tx/config
7474
.tx/config
File diff suppressed because it is too large
Load Diff
6492
CHANGELOG.md
6492
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
51
Dockerfile
51
Dockerfile
@@ -1,51 +1,22 @@
|
||||
FROM --platform=$BUILDPLATFORM node:lts as npm
|
||||
FROM node:lts
|
||||
|
||||
RUN mkdir -p /usr/src/build && \
|
||||
chown -R node:node /usr/src/build
|
||||
WORKDIR /usr/src/build
|
||||
RUN mkdir -p /usr/src/app
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
ARG NODE_ENV
|
||||
ENV NODE_ENV $NODE_ENV
|
||||
|
||||
COPY --chown=node:node install/package.json /usr/src/build/package.json
|
||||
COPY install/package.json /usr/src/app/package.json
|
||||
|
||||
USER node
|
||||
RUN npm install --only=prod && \
|
||||
npm cache clean --force
|
||||
|
||||
COPY . /usr/src/app
|
||||
|
||||
RUN npm install --omit=dev
|
||||
|
||||
FROM node:lts as rebuild
|
||||
|
||||
ARG BUILDPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
RUN mkdir -p /usr/src/build && \
|
||||
chown -R node:node /usr/src/build
|
||||
|
||||
COPY --from=npm /usr/src/build /usr/src/build
|
||||
|
||||
RUN if [ $BUILDPLATFORM != $TARGETPLATFORM ]; then \
|
||||
npm rebuild && \
|
||||
npm cache clean --force; fi
|
||||
|
||||
FROM node:lts-slim as run
|
||||
|
||||
ARG NODE_ENV
|
||||
ENV NODE_ENV=$NODE_ENV \
|
||||
ENV NODE_ENV=production \
|
||||
daemon=false \
|
||||
silent=false
|
||||
|
||||
RUN mkdir -p /usr/src/app && \
|
||||
chown -R node:node /usr/src/app
|
||||
|
||||
COPY --chown=node:node --from=rebuild /usr/src/build /usr/src/app
|
||||
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
USER node
|
||||
|
||||
COPY --chown=node:node . /usr/src/app
|
||||
|
||||
EXPOSE 4567
|
||||
VOLUME ["/usr/src/app/node_modules", "/usr/src/app/build", "/usr/src/app/public/uploads", "/opt/config"]
|
||||
ENTRYPOINT ["./install/docker/entrypoint.sh"]
|
||||
|
||||
CMD node ./nodebb build ; node ./nodebb start
|
||||
|
||||
117
Gruntfile.js
117
Gruntfile.js
@@ -2,28 +2,24 @@
|
||||
|
||||
const path = require('path');
|
||||
const nconf = require('nconf');
|
||||
|
||||
nconf.argv().env({
|
||||
separator: '__',
|
||||
});
|
||||
const winston = require('winston');
|
||||
const { fork } = require('child_process');
|
||||
|
||||
const { env } = process;
|
||||
let worker;
|
||||
const fork = require('child_process').fork;
|
||||
const env = process.env;
|
||||
var worker;
|
||||
|
||||
env.NODE_ENV = env.NODE_ENV || 'development';
|
||||
|
||||
const configFile = path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'config.json');
|
||||
const prestart = require('./src/prestart');
|
||||
|
||||
prestart.loadConfig(configFile);
|
||||
|
||||
const db = require('./src/database');
|
||||
const plugins = require('./src/plugins');
|
||||
var db = require('./src/database');
|
||||
|
||||
module.exports = function (grunt) {
|
||||
const args = [];
|
||||
var args = [];
|
||||
|
||||
if (!grunt.option('verbose')) {
|
||||
args.push('--log-level=info');
|
||||
@@ -40,51 +36,64 @@ module.exports = function (grunt) {
|
||||
grunt.registerTask('default', ['watch']);
|
||||
|
||||
grunt.registerTask('init', async function () {
|
||||
const done = this.async();
|
||||
let pluginList = [];
|
||||
var done = this.async();
|
||||
let plugins = [];
|
||||
if (!process.argv.includes('--core')) {
|
||||
await db.init();
|
||||
pluginList = await plugins.getActive();
|
||||
addBaseThemes(pluginList);
|
||||
if (!pluginList.includes('nodebb-plugin-composer-default')) {
|
||||
pluginList.push('nodebb-plugin-composer-default');
|
||||
plugins = await db.getSortedSetRange('plugins:active', 0, -1);
|
||||
addBaseThemes(plugins);
|
||||
if (!plugins.includes('nodebb-plugin-composer-default')) {
|
||||
plugins.push('nodebb-plugin-composer-default');
|
||||
}
|
||||
if (!pluginList.includes('nodebb-theme-harmony')) {
|
||||
pluginList.push('nodebb-theme-harmony');
|
||||
if (!plugins.includes('nodebb-theme-persona')) {
|
||||
plugins.push('nodebb-theme-persona');
|
||||
}
|
||||
}
|
||||
|
||||
const styleUpdated_Client = pluginList.map(p => `node_modules/${p}/*.scss`)
|
||||
.concat(pluginList.map(p => `node_modules/${p}/*.css`))
|
||||
.concat(pluginList.map(p => `node_modules/${p}/+(public|static|scss)/**/*.scss`))
|
||||
.concat(pluginList.map(p => `node_modules/${p}/+(public|static)/**/*.css`));
|
||||
const styleUpdated_Client = plugins.map(p => 'node_modules/' + p + '/*.less')
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/*.css'))
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static|less)/**/*.less'))
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.css'));
|
||||
|
||||
const clientUpdated = pluginList.map(p => `node_modules/${p}/+(public|static)/**/*.js`);
|
||||
const serverUpdated = pluginList.map(p => `node_modules/${p}/*.js`)
|
||||
.concat(pluginList.map(p => `node_modules/${p}/+(lib|src)/**/*.js`));
|
||||
const styleUpdated_Admin = plugins.map(p => 'node_modules/' + p + '/*.less')
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/*.css'))
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static|less)/**/*.less'))
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.css'));
|
||||
|
||||
const clientUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.js');
|
||||
const serverUpdated = plugins.map(p => 'node_modules/' + p + '/*.js')
|
||||
.concat(plugins.map(p => 'node_modules/' + p + '/+(lib|src)/**/*.js'));
|
||||
|
||||
const templatesUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static|templates)/**/*.tpl');
|
||||
const langUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static|languages)/**/*.json');
|
||||
|
||||
const templatesUpdated = pluginList.map(p => `node_modules/${p}/+(public|static|templates)/**/*.tpl`);
|
||||
const langUpdated = pluginList.map(p => `node_modules/${p}/+(public|static|languages)/**/*.json`);
|
||||
const interval = 100;
|
||||
grunt.config(['watch'], {
|
||||
styleUpdated: {
|
||||
styleUpdated_Client: {
|
||||
files: [
|
||||
'public/scss/**/*.scss',
|
||||
'public/less/**/*.less',
|
||||
...styleUpdated_Client,
|
||||
],
|
||||
options: {
|
||||
interval: interval,
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
styleUpdated_Admin: {
|
||||
files: [
|
||||
'public/less/**/*.less',
|
||||
...styleUpdated_Admin,
|
||||
],
|
||||
options: {
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
clientUpdated: {
|
||||
files: [
|
||||
'public/src/**/*.js',
|
||||
'public/vendor/**/*.js',
|
||||
...clientUpdated,
|
||||
'node_modules/benchpressjs/build/benchpress.js',
|
||||
],
|
||||
options: {
|
||||
interval: interval,
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
serverUpdated: {
|
||||
@@ -92,14 +101,14 @@ module.exports = function (grunt) {
|
||||
'app.js',
|
||||
'install/*.js',
|
||||
'src/**/*.js',
|
||||
'public/src/modules/translator.common.js',
|
||||
'public/src/modules/helpers.common.js',
|
||||
'public/src/utils.common.js',
|
||||
'public/src/modules/translator.js',
|
||||
'public/src/modules/helpers.js',
|
||||
'public/src/utils.js',
|
||||
serverUpdated,
|
||||
'!src/upgrades/**',
|
||||
],
|
||||
options: {
|
||||
interval: interval,
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
templatesUpdated: {
|
||||
@@ -108,7 +117,7 @@ module.exports = function (grunt) {
|
||||
...templatesUpdated,
|
||||
],
|
||||
options: {
|
||||
interval: interval,
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
langUpdated: {
|
||||
@@ -118,13 +127,13 @@ module.exports = function (grunt) {
|
||||
...langUpdated,
|
||||
],
|
||||
options: {
|
||||
interval: interval,
|
||||
interval: 1000,
|
||||
},
|
||||
},
|
||||
});
|
||||
const build = require('./src/meta/build');
|
||||
if (!grunt.option('skip')) {
|
||||
await build.build(true, { watch: true });
|
||||
await build.build(true);
|
||||
}
|
||||
run();
|
||||
done();
|
||||
@@ -151,16 +160,18 @@ module.exports = function (grunt) {
|
||||
grunt.task.run('init');
|
||||
|
||||
grunt.event.removeAllListeners('watch');
|
||||
grunt.event.on('watch', (action, filepath, target) => {
|
||||
let compiling;
|
||||
if (target === 'styleUpdated') {
|
||||
compiling = ['clientCSS', 'acpCSS'];
|
||||
grunt.event.on('watch', function update(action, filepath, target) {
|
||||
var compiling;
|
||||
if (target === 'styleUpdated_Client') {
|
||||
compiling = 'clientCSS';
|
||||
} else if (target === 'styleUpdated_Admin') {
|
||||
compiling = 'acpCSS';
|
||||
} else if (target === 'clientUpdated') {
|
||||
compiling = ['js'];
|
||||
compiling = 'js';
|
||||
} else if (target === 'templatesUpdated') {
|
||||
compiling = ['tpl'];
|
||||
compiling = 'tpl';
|
||||
} else if (target === 'langUpdated') {
|
||||
compiling = ['lang'];
|
||||
compiling = 'lang';
|
||||
} else if (target === 'serverUpdated') {
|
||||
// empty require cache
|
||||
const paths = ['./src/meta/build.js', './src/meta/index.js'];
|
||||
@@ -168,7 +179,7 @@ module.exports = function (grunt) {
|
||||
return run();
|
||||
}
|
||||
|
||||
require('./src/meta/build').build(compiling, { webpack: false }, (err) => {
|
||||
require('./src/meta/build').build([compiling], function (err) {
|
||||
if (err) {
|
||||
winston.error(err.stack);
|
||||
}
|
||||
@@ -179,23 +190,23 @@ module.exports = function (grunt) {
|
||||
});
|
||||
};
|
||||
|
||||
function addBaseThemes(pluginList) {
|
||||
let themeId = pluginList.find(p => p.includes('nodebb-theme-'));
|
||||
function addBaseThemes(plugins) {
|
||||
let themeId = plugins.find(p => p.includes('nodebb-theme-'));
|
||||
if (!themeId) {
|
||||
return pluginList;
|
||||
return plugins;
|
||||
}
|
||||
let baseTheme;
|
||||
do {
|
||||
try {
|
||||
baseTheme = require(`${themeId}/theme`).baseTheme;
|
||||
baseTheme = require(themeId + '/theme').baseTheme;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
if (baseTheme) {
|
||||
pluginList.push(baseTheme);
|
||||
plugins.push(baseTheme);
|
||||
themeId = baseTheme;
|
||||
}
|
||||
} while (baseTheme);
|
||||
return pluginList;
|
||||
return plugins;
|
||||
}
|
||||
|
||||
51
README.md
51
README.md
@@ -1,15 +1,22 @@
|
||||
# 
|
||||
# 
|
||||
|
||||
[](https://github.com/NodeBB/NodeBB/actions/workflows/test.yaml)
|
||||
[](https://travis-ci.org/NodeBB/NodeBB)
|
||||
[](https://coveralls.io/github/NodeBB/NodeBB?branch=master)
|
||||
[](https://david-dm.org/nodebb/nodebb?path=install)
|
||||
[](https://codeclimate.com/github/NodeBB/NodeBB)
|
||||
[](https://discord.gg/p6YKPXu7er)
|
||||
|
||||
[**NodeBB Forum Software**](https://nodebb.org) is powered by Node.js and supports either Redis, MongoDB, or a PostgreSQL database. It utilizes web sockets for instant interactions and real-time notifications. NodeBB takes the best of the modern web: real-time streaming discussions, mobile responsiveness, and rich RESTful read/write APIs, while staying true to the original bulletin board/forum format → categorical hierarchies, local user accounts, and asynchronous messaging.
|
||||
[**NodeBB Forum Software**](https://nodebb.org) is powered by Node.js and supports either Redis, MongoDB, or a PostgreSQL database. It utilizes web sockets for instant interactions and real-time notifications. NodeBB has many modern features out of the box such as social network integration and streaming discussions, while still making sure to be compatible with older browsers.
|
||||
|
||||
NodeBB by itself contains a "common core" of basic functionality, while additional functionality and integrations are enabled through the use of third-party plugins.
|
||||
Additional functionality is enabled through the use of third-party plugins.
|
||||
|
||||
### [Try it now](//try.nodebb.org) | [Documentation](//docs.nodebb.org)
|
||||
* [Demo](https://try.nodebb.org)
|
||||
* [Developer Community](http://community.nodebb.org)
|
||||
* [Documentation & Installation Instructions](http://docs.nodebb.org)
|
||||
* [Help translate NodeBB](https://www.transifex.com/projects/p/nodebb/)
|
||||
* [NodeBB Blog](http://blog.nodebb.org)
|
||||
* [Premium Hosting for NodeBB](http://www.nodebb.org/ "NodeBB")
|
||||
* [Follow us on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter")
|
||||
* [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
|
||||
## Screenshots
|
||||
|
||||
@@ -24,30 +31,31 @@ NodeBB's theming engine is highly flexible and does not restrict your design cho
|
||||
[](http://i.imgur.com/LmHtPho.png)
|
||||
[](http://i.imgur.com/paiJPJk.jpg)
|
||||
|
||||
Our minimalist "Harmony" theme gets you going right away, no coding experience required.
|
||||
Our minimalist "Persona" theme gets you going right away, no coding experience required.
|
||||
|
||||
[](http://i.imgur.com/HwNEXGu.png)
|
||||
[](http://i.imgur.com/II1byYs.png)
|
||||
|
||||
|
||||

|
||||
|
||||
## How can I follow along/contribute?
|
||||
|
||||
* If you are a developer, feel free to check out the source and submit pull requests. We also have a wide array of [plugins](http://community.nodebb.org/category/7/nodebb-plugins) which would be a great starting point for learning the codebase.
|
||||
* If you are a designer, [NodeBB needs themes](http://community.nodebb.org/category/10/nodebb-themes)! NodeBB's theming system allows extension of the base templates as well as styling via SCSS or CSS. NodeBB's base theme utilizes [Bootstrap 5](http://getbootstrap.com/) as a frontend toolkit.
|
||||
* If you know languages other than English you can help us translate NodeBB. We use [Transifex](https://explore.transifex.com/nodebb/nodebb/) for internationalization.
|
||||
* If you are a designer, [NodeBB needs themes](http://community.nodebb.org/category/10/nodebb-themes)! NodeBB's theming system allows extension of the base templates as well as styling via LESS or CSS. NodeBB's base theme utilizes [Bootstrap 3](http://getbootstrap.com/) but themes can choose to use a different framework altogether.
|
||||
* If you know languages other than English you can help us translate NodeBB. We use [Transifex](https://www.transifex.com/projects/p/nodebb/) for internationalization.
|
||||
* Please don't forget to **like**, **follow**, and **star our repo**! Join our growing [community](http://community.nodebb.org) to keep up to date with the latest NodeBB development.
|
||||
|
||||
## Requirements
|
||||
|
||||
NodeBB requires the following software to be installed:
|
||||
|
||||
* A version of Node.js at least 16 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
||||
* MongoDB, version 3.6 or greater **or** Redis, version 2.8.9 or greater
|
||||
* If you are using [clustering](https://docs.nodebb.org/configuring/scaling/) you need Redis installed and configured.
|
||||
* A version of Node.js at least 12 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
||||
* MongoDB, version 2.6 or greater **or** Redis, version 2.8.9 or greater
|
||||
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
||||
|
||||
## Installation
|
||||
|
||||
[Please refer to platform-specific installation documentation](https://docs.nodebb.org/installing/os).
|
||||
If installing via the cloud (or using Docker), [please see cloud-based installation documentation](https://docs.nodebb.org/installing/cloud/).
|
||||
[Please refer to platform-specific installation documentation](https://docs.nodebb.org/installing/os)
|
||||
|
||||
## Securing NodeBB
|
||||
|
||||
@@ -60,7 +68,6 @@ It is important to ensure that your NodeBB and database servers are secured. Bea
|
||||
2. Use `iptables` to secure your server from unintended open ports. In Ubuntu, `ufw` provides a friendlier interface to working with `iptables`.
|
||||
* e.g. If your NodeBB is proxied, no ports should be open except 80 (and possibly 22, for SSH access)
|
||||
|
||||
|
||||
## Upgrading NodeBB
|
||||
|
||||
Detailed upgrade instructions are listed in [Upgrading NodeBB](https://docs.nodebb.org/configuring/upgrade/)
|
||||
@@ -70,15 +77,3 @@ Detailed upgrade instructions are listed in [Upgrading NodeBB](https://docs.node
|
||||
NodeBB is licensed under the **GNU General Public License v3 (GPL-3)** (http://www.gnu.org/copyleft/gpl.html).
|
||||
|
||||
Interested in a sublicense agreement for use of NodeBB in a non-free/restrictive environment? Contact us at sales@nodebb.org.
|
||||
|
||||
## More Information/Links
|
||||
|
||||
* [Demo](https://try.nodebb.org)
|
||||
* [Developer Community](http://community.nodebb.org)
|
||||
* [Documentation & Installation Instructions](https://docs.nodebb.org)
|
||||
* [Help translate NodeBB](https://explore.transifex.com/nodebb/nodebb/)
|
||||
* [NodeBB Blog](https://nodebb.org/blog)
|
||||
* [Premium Hosting for NodeBB](https://www.nodebb.org/ "NodeBB")
|
||||
* Unofficial IRC community – channel `#nodebb` on Libera.chat
|
||||
* [Follow us on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter")
|
||||
* [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
|
||||
8
app.js
8
app.js
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
NodeBB - A better forum platform for the modern web
|
||||
https://github.com/NodeBB/NodeBB/
|
||||
Copyright (C) 2013-2021 NodeBB Inc.
|
||||
Copyright (C) 2013-2017 NodeBB Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,7 +22,6 @@
|
||||
require('./require-main');
|
||||
|
||||
const nconf = require('nconf');
|
||||
|
||||
nconf.argv().env({
|
||||
separator: '__',
|
||||
});
|
||||
@@ -41,7 +40,6 @@ const configFile = path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'c
|
||||
const configExists = file.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
|
||||
|
||||
const prestart = require('./src/prestart');
|
||||
|
||||
prestart.loadConfig(configFile);
|
||||
prestart.setupWinston();
|
||||
prestart.versionCheck();
|
||||
@@ -49,7 +47,7 @@ winston.verbose('* using configuration stored in: %s', configFile);
|
||||
|
||||
if (!process.send) {
|
||||
// If run using `node app`, log GNU copyright info along with server info
|
||||
winston.info(`NodeBB v${nconf.get('version')} Copyright (C) 2013-${(new Date()).getFullYear()} NodeBB Inc.`);
|
||||
winston.info('NodeBB v' + nconf.get('version') + ' Copyright (C) 2013-' + (new Date()).getFullYear() + ' NodeBB Inc.');
|
||||
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
|
||||
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
winston.info('');
|
||||
@@ -71,7 +69,7 @@ if (nconf.get('setup') || nconf.get('install')) {
|
||||
});
|
||||
} else if (nconf.get('activate')) {
|
||||
require('./src/cli/manage').activate(nconf.get('activate'));
|
||||
} else if (nconf.get('plugins') && typeof nconf.get('plugins') !== 'object') {
|
||||
} else if (nconf.get('plugins')) {
|
||||
require('./src/cli/manage').listPlugins();
|
||||
} else if (nconf.get('build')) {
|
||||
require('./src/cli/manage').build(nconf.get('build'));
|
||||
|
||||
@@ -1,55 +1,24 @@
|
||||
version: '3.8'
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
nodebb:
|
||||
node:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "4567:4567/tcp" # comment this out if you don't want to expose NodeBB to the host, or change the first number to any port you want
|
||||
# uncomment if you want to use another container as a reverse proxy
|
||||
# expose:
|
||||
# - 4567
|
||||
depends_on:
|
||||
- db
|
||||
expose:
|
||||
- 4567 # use a reverse proxy like Traefik
|
||||
|
||||
db:
|
||||
image: mongo:bionic
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 27017
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: root
|
||||
volumes:
|
||||
- ./.docker/build:/usr/src/app/build
|
||||
- ./.docker/public/uploads:/usr/src/app/public/uploads
|
||||
- ./.docker:/opt/config
|
||||
- ./install/docker/setup.json:/usr/src/app/setup.json
|
||||
- mongo:/data/db
|
||||
|
||||
volumes:
|
||||
mongo:
|
||||
image: "mongo:7-jammy"
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "27017"
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: nodebb
|
||||
MONGO_INITDB_ROOT_PASSWORD: nodebb
|
||||
MONGO_INITDB_DATABASE: nodebb
|
||||
volumes:
|
||||
- ./.docker/database/mongo/config:/etc/mongo
|
||||
- ./.docker/database/mongo/data:/data/db
|
||||
- ./install/docker/mongodb-user-init.js:/docker-entrypoint-initdb.d/user-init.js
|
||||
profiles:
|
||||
- mongo
|
||||
postgres:
|
||||
image: postgres:16.1-alpine
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "5432"
|
||||
environment:
|
||||
POSTGRES_USER: nodebb
|
||||
POSTGRES_PASSWORD: nodebb
|
||||
POSTGRES_DB: nodebb
|
||||
volumes:
|
||||
- ./.docker/database/postgresql/data:/var/lib/postgresql/data
|
||||
profiles:
|
||||
- postgres
|
||||
redis:
|
||||
image: redis:7.2.3-alpine
|
||||
restart: unless-stopped
|
||||
command: ["redis-server", "--appendonly", "yes", "--loglevel", "warning"]
|
||||
# command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"] # uncomment if you want to use snapshotting instead of AOF
|
||||
expose:
|
||||
- "6379"
|
||||
volumes:
|
||||
- ./.docker/database/redis:/data
|
||||
profiles:
|
||||
- redis
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "Announcements regarding our community",
|
||||
"descriptionParsed": "<p>Announcements regarding our community</p>\n",
|
||||
"bgColor": "#fda34b",
|
||||
"color": "#ffffff",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-bullhorn",
|
||||
"order": 1
|
||||
},
|
||||
@@ -13,7 +13,7 @@
|
||||
"description": "A place to talk about whatever you want",
|
||||
"descriptionParsed": "<p>A place to talk about whatever you want</p>\n",
|
||||
"bgColor": "#59b3d0",
|
||||
"color": "#ffffff",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-comments-o",
|
||||
"order": 2
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"description": "Blog posts from individual members",
|
||||
"descriptionParsed": "<p>Blog posts from individual members</p>\n",
|
||||
"bgColor": "#86ba4b",
|
||||
"color": "#ffffff",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-newspaper-o",
|
||||
"order": 4
|
||||
},
|
||||
@@ -31,7 +31,7 @@
|
||||
"description": "Got a question? Ask away!",
|
||||
"descriptionParsed": "<p>Got a question? Ask away!</p>\n",
|
||||
"bgColor": "#e95c5a",
|
||||
"color": "#ffffff",
|
||||
"color": "#fff",
|
||||
"icon" : "fa-question",
|
||||
"order": 3
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
"defaultLang": "en-GB",
|
||||
"loginDays": 14,
|
||||
"loginSeconds": 0,
|
||||
"sessionDuration": 0,
|
||||
"loginAttempts": 5,
|
||||
"lockoutDuration": 60,
|
||||
"adminReloginDuration": 60,
|
||||
@@ -15,47 +14,36 @@
|
||||
"newbiePostEditDuration": 3600,
|
||||
"postDeleteDuration": 0,
|
||||
"enablePostHistory": 1,
|
||||
"topicBacklinks": 1,
|
||||
"postCacheSize": 20971520,
|
||||
"postCacheSize": 10485760,
|
||||
"disableChat": 0,
|
||||
"chatEditDuration": 0,
|
||||
"chatDeleteDuration": 0,
|
||||
"chatMessageDelay": 2000,
|
||||
"newbieChatMessageDelay": 120000,
|
||||
"notificationSendDelay": 60,
|
||||
"newbieReputationThreshold": 3,
|
||||
"postQueue": 0,
|
||||
"chatMessageDelay": 200,
|
||||
"newbiePostDelayThreshold": 3,
|
||||
"postQueueReputationThreshold": 0,
|
||||
"groupsExemptFromPostQueue": ["administrators", "Global Moderators"],
|
||||
"groupsExemptFromNewUserRestrictions": ["administrators", "Global Moderators"],
|
||||
"groupsExemptFromMaintenanceMode": ["administrators", "Global Moderators"],
|
||||
"minimumPostLength": 8,
|
||||
"maximumPostLength": 32767,
|
||||
"systemTags": "",
|
||||
"minimumTagsPerTopic": 0,
|
||||
"maximumTagsPerTopic": 5,
|
||||
"minimumTagLength": 3,
|
||||
"maximumTagLength": 15,
|
||||
"undoTimeout": 10000,
|
||||
"allowTopicsThumbnail": 1,
|
||||
"allowTopicsThumbnail": 0,
|
||||
"registrationType": "normal",
|
||||
"registrationApprovalType": "normal",
|
||||
"allowAccountDelete": 1,
|
||||
"privateUploads": 0,
|
||||
"allowedFileExtensions": "png,jpg,bmp,txt",
|
||||
"uploadRateLimitThreshold": 10,
|
||||
"uploadRateLimitCooldown": 60,
|
||||
"allowUserHomePage": 1,
|
||||
"allowMultipleBadges": 0,
|
||||
"maximumFileSize": 2048,
|
||||
"stripEXIFData": 1,
|
||||
"orphanExpiryDays": 0,
|
||||
"resizeImageWidthThreshold": 2000,
|
||||
"resizeImageWidth": 760,
|
||||
"rejectImageWidth": 5000,
|
||||
"rejectImageHeight": 5000,
|
||||
"resizeImageQuality": 80,
|
||||
"topicThumbSize": 512,
|
||||
"topicThumbSize": 120,
|
||||
"minimumTitleLength": 3,
|
||||
"maximumTitleLength": 255,
|
||||
"minimumUsernameLength": 2,
|
||||
@@ -66,16 +54,15 @@
|
||||
"maximumAboutMeLength": 1000,
|
||||
"maximumUsersInChatRoom": 0,
|
||||
"maximumChatMessageLength": 1000,
|
||||
"maximumChatRoomNameLength": 50,
|
||||
"maximumProfileImageSize": 256,
|
||||
"maximumCoverImageSize": 2048,
|
||||
"profileImageDimension": 200,
|
||||
"profile:convertProfileImageToPNG": 0,
|
||||
"profile:keepAllUserImages": 0,
|
||||
"requireEmailConfirmation": 0,
|
||||
"gdpr_enabled": 1,
|
||||
"allowProfileImageUploads": 1,
|
||||
"teaserPost": "last-reply",
|
||||
"showPostPreviewsOnHover": 1,
|
||||
"allowPrivateGroups": 1,
|
||||
"unreadCutoff": 2,
|
||||
"bookmarkThreshold": 5,
|
||||
@@ -83,15 +70,9 @@
|
||||
"reputation:disabled": 0,
|
||||
"downvote:disabled": 0,
|
||||
"disableSignatures": 0,
|
||||
"signatures:hideDuplicates": 0,
|
||||
"upvotesPerDay": 20,
|
||||
"upvotesPerUserPerDay": 6,
|
||||
"downvotesPerDay": 10,
|
||||
"downvotesPerUserPerDay": 3,
|
||||
"min:rep:chat": 0,
|
||||
"min:rep:downvote": 0,
|
||||
"min:rep:upvote": 0,
|
||||
"min:rep:post-links": 0,
|
||||
"min:rep:flag": 0,
|
||||
"min:rep:profile-picture": 0,
|
||||
"min:rep:cover-picture": 0,
|
||||
@@ -99,9 +80,6 @@
|
||||
"min:rep:aboutme": 0,
|
||||
"min:rep:signature": 0,
|
||||
"flags:limitPerTarget": 0,
|
||||
"flags:autoFlagOnDownvoteThreshold": 0,
|
||||
"flags:actionOnResolve": "rescind",
|
||||
"flags:actionOnReject": "rescind",
|
||||
"notificationType_upvote": "notification",
|
||||
"notificationType_new-topic": "notification",
|
||||
"notificationType_new-reply": "notification",
|
||||
@@ -110,7 +88,6 @@
|
||||
"notificationType_new-chat": "notification",
|
||||
"notificationType_new-group-chat": "notification",
|
||||
"notificationType_group-invite": "notification",
|
||||
"notificationType_group-leave": "notification",
|
||||
"notificationType_group-request-membership": "notification",
|
||||
"notificationType_mention": "notification",
|
||||
"notificationType_new-register": "notification",
|
||||
@@ -122,16 +99,11 @@
|
||||
"maxPostsPerPage": 20,
|
||||
"topicsPerPage": 20,
|
||||
"postsPerPage": 20,
|
||||
"categoriesPerPage": 50,
|
||||
"userSearchResultsPerPage": 50,
|
||||
"searchDefaultSortBy": "relevance",
|
||||
"searchDefaultIn": "titlesposts",
|
||||
"searchDefaultInQuick": "titles",
|
||||
"maximumGroupNameLength": 255,
|
||||
"maximumGroupTitleLength": 40,
|
||||
"preventTopicDeleteAfterReplies": 0,
|
||||
"feeds:disableSitemap": 0,
|
||||
"feeds:disableRSS": 0,
|
||||
"sitemapTopics": 500,
|
||||
"maintenanceMode": 0,
|
||||
"maintenanceModeStatus": 503,
|
||||
@@ -139,7 +111,7 @@
|
||||
"maximumInvites": 0,
|
||||
"username:disableEdit": 0,
|
||||
"email:disableEdit": 0,
|
||||
"email:smtpTransport:pool": 0,
|
||||
"email:smtpTransport:pool": false,
|
||||
"hideFullname": 0,
|
||||
"hideEmail": 0,
|
||||
"showFullnameAsDisplayName": 0,
|
||||
@@ -152,20 +124,10 @@
|
||||
"maximumRelatedTopics": 0,
|
||||
"disableEmailSubscriptions": 0,
|
||||
"emailConfirmInterval": 10,
|
||||
"emailConfirmExpiry": 24,
|
||||
"removeEmailNotificationImages": 0,
|
||||
"sendValidationEmail": 1,
|
||||
"includeUnverifiedEmails": 0,
|
||||
"emailPrompt": 1,
|
||||
"sendEmailToBanned": 0,
|
||||
"requireEmailAddress": 0,
|
||||
"inviteExpiration": 7,
|
||||
"dailyDigestFreq": "off",
|
||||
"digestHour": 17,
|
||||
"passwordExpiryDays": 0,
|
||||
"cross-origin-embedder-policy": 0,
|
||||
"cross-origin-opener-policy": "same-origin",
|
||||
"cross-origin-resource-policy": "same-origin",
|
||||
"hsts-maxage": 31536000,
|
||||
"hsts-subdomains": 0,
|
||||
"hsts-preload": 0,
|
||||
@@ -178,14 +140,9 @@
|
||||
"necroThreshold": 7,
|
||||
"categoryWatchState": "watching",
|
||||
"submitPluginUsage": 1,
|
||||
"showAverageApprovalTime": 1,
|
||||
"showAverageApprovalTime": true,
|
||||
"autoApproveTime": 0,
|
||||
"maxUserSessions": 10,
|
||||
"useCompression": 0,
|
||||
"updateUrlWithPostIndex": 1,
|
||||
"composer:showHelpTab": 1,
|
||||
"composer:allowPluginHelp": 1,
|
||||
"maxReconnectionAttempts": 5,
|
||||
"reconnectionDelay": 1500,
|
||||
"disableCustomUserSkins": 0
|
||||
"updateUrlWithPostIndex": 1
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"widget": "html",
|
||||
"data" : {
|
||||
"html": "<footer id=\"footer\" class=\"container footer d-flex flex-column align-items-center gap-1 mb-2\">\n\t<span>Powered by <a class=\"link-secondary text-decoration-underline\" target=\"_blank\" href=\"https://nodebb.org\">NodeBB</a></span>\n\t<span><a class=\"link-secondary\" target=\"_blank\" href=\"//github.com/NodeBB/NodeBB/graphs/contributors\"><i class=\"fa fa-users\"></i> <span class=\"text-decoration-underline\">Contributors<span></a></span>\n</footer>",
|
||||
"html": "<footer id=\"footer\" class=\"container footer\">\r\n\t<div>\r\n\t\tPowered by <a target=\"_blank\" href=\"https://nodebb.org\">NodeBB</a> | <a target=\"_blank\" href=\"//github.com/NodeBB/NodeBB/graphs/contributors\">Contributors</a>\r\n\t</div>\r\n</footer>",
|
||||
"title":"",
|
||||
"container":""
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"title": "[[global:header.categories]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-list",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.categories]]"
|
||||
},
|
||||
{
|
||||
@@ -13,7 +13,7 @@
|
||||
"title": "[[global:header.unread]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-inbox",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.unread]]",
|
||||
"groups": ["registered-users"]
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"title": "[[global:header.recent]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-clock-o",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.recent]]"
|
||||
},
|
||||
{
|
||||
@@ -30,7 +30,7 @@
|
||||
"title": "[[global:header.tags]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-tags",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.tags]]"
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"title": "[[global:header.popular]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-fire",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.popular]]"
|
||||
},
|
||||
{
|
||||
@@ -46,7 +46,7 @@
|
||||
"title": "[[global:header.users]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-user",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.users]]"
|
||||
},
|
||||
{
|
||||
@@ -54,7 +54,7 @@
|
||||
"title": "[[global:header.groups]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-group",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.groups]]"
|
||||
},
|
||||
{
|
||||
@@ -62,8 +62,11 @@
|
||||
"title": "[[global:header.admin]]",
|
||||
"enabled": true,
|
||||
"iconClass": "fa-cogs",
|
||||
"textClass": "d-lg-none",
|
||||
"textClass": "visible-xs-inline",
|
||||
"text": "[[global:header.admin]]",
|
||||
"groups": ["administrators"]
|
||||
"groups": ["administrators"],
|
||||
"properties": {
|
||||
"targetBlank": false
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,9 +1,9 @@
|
||||
### Welcome to your brand new NodeBB forum!
|
||||
# Welcome to your brand new NodeBB forum!
|
||||
|
||||
This is what a topic and post looks like. As an administrator, you can edit the post\'s title and content.
|
||||
To customise your forum, go to the [Administrator Control Panel](../../admin). You can modify all aspects of your forum there, including installation of third-party plugins.
|
||||
|
||||
#### Additional Resources
|
||||
## Additional Resources
|
||||
|
||||
* [NodeBB Documentation](https://docs.nodebb.org)
|
||||
* [Community Support Forum](https://community.nodebb.org)
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
const prompt = require('prompt');
|
||||
const winston = require('winston');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const promptGet = util.promisify((schema, callback) => prompt.get(schema, callback));
|
||||
|
||||
const questions = {
|
||||
redis: require('../src/database/redis').questions,
|
||||
mongo: require('../src/database/mongo').questions,
|
||||
@@ -10,7 +14,7 @@ const questions = {
|
||||
};
|
||||
|
||||
module.exports = async function (config) {
|
||||
winston.info(`\nNow configuring ${config.database} database:`);
|
||||
winston.info('\nNow configuring ' + config.database + ' database:');
|
||||
const databaseConfig = await getDatabaseConfig(config);
|
||||
return saveDatabaseConfig(config, databaseConfig);
|
||||
};
|
||||
@@ -24,19 +28,19 @@ async function getDatabaseConfig(config) {
|
||||
if (config['redis:host'] && config['redis:port']) {
|
||||
return config;
|
||||
}
|
||||
return await prompt.get(questions.redis);
|
||||
return await promptGet(questions.redis);
|
||||
} else if (config.database === 'mongo') {
|
||||
if ((config['mongo:host'] && config['mongo:port']) || config['mongo:uri']) {
|
||||
return config;
|
||||
}
|
||||
return await prompt.get(questions.mongo);
|
||||
return await promptGet(questions.mongo);
|
||||
} else if (config.database === 'postgres') {
|
||||
if (config['postgres:host'] && config['postgres:port']) {
|
||||
return config;
|
||||
}
|
||||
return await prompt.get(questions.postgres);
|
||||
return await promptGet(questions.postgres);
|
||||
}
|
||||
throw new Error(`unknown database : ${config.database}`);
|
||||
throw new Error('unknown database : ' + config.database);
|
||||
}
|
||||
|
||||
function saveDatabaseConfig(config, databaseConfig) {
|
||||
@@ -75,11 +79,11 @@ function saveDatabaseConfig(config, databaseConfig) {
|
||||
ssl: databaseConfig['postgres:ssl'],
|
||||
};
|
||||
} else {
|
||||
throw new Error(`unknown database : ${config.database}`);
|
||||
throw new Error('unknown database : ' + config.database);
|
||||
}
|
||||
|
||||
const allQuestions = questions.redis.concat(questions.mongo).concat(questions.postgres);
|
||||
for (let x = 0; x < allQuestions.length; x += 1) {
|
||||
for (var x = 0; x < allQuestions.length; x += 1) {
|
||||
delete config[allQuestions[x].name];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export CONFIG_DIR="${CONFIG_DIR:-/opt/config}"
|
||||
export CONFIG=$CONFIG_DIR/config.json
|
||||
export FORCE_BUILD_BEFORE_START="${FORCE_BUILD_BEFORE_START:-false}"
|
||||
|
||||
# Supported verbs: install (web install), setup (interactive CLI session). Default: web install
|
||||
# TODO: constraint it using a hash set (or hash table)
|
||||
export NODEBB_INIT_VERB="${NODEBB_INIT_VERB:-install}"
|
||||
# Setup variable for backward compatibility, default: <empty>
|
||||
export SETUP="${SETUP:-}"
|
||||
|
||||
mkdir -p $CONFIG_DIR
|
||||
|
||||
# if the folder is mounted as a volume this can fail, the check below is to ensure there is still write access
|
||||
chmod -fR 760 $CONFIG_DIR 2> /dev/null
|
||||
|
||||
if [[ ! -w $CONFIG_DIR ]]; then
|
||||
echo "panic: no write permission for $CONFIG_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[[ -f $CONFIG_DIR/package.json ]] || cp install/package.json $CONFIG_DIR/package.json
|
||||
[[ -f $CONFIG_DIR/package-lock.json ]] || touch $CONFIG_DIR/package-lock.json
|
||||
|
||||
ln -fs $CONFIG_DIR/package.json package.json
|
||||
ln -fs $CONFIG_DIR/package-lock.json package-lock.json
|
||||
|
||||
npm install --omit=dev
|
||||
|
||||
if [[ -n $SETUP ]]; then
|
||||
echo "Setup environmental variable detected"
|
||||
echo "Starting setup session"
|
||||
./nodebb setup --config=$CONFIG
|
||||
elif [ -f $CONFIG ]; then
|
||||
echo "Config file exist at $CONFIG, assuming it is a valid config"
|
||||
echo "Starting forum"
|
||||
if [ "$FORCE_BUILD_BEFORE_START" = true ]; then
|
||||
./nodebb build --config=$CONFIG
|
||||
fi
|
||||
./nodebb start --config=$CONFIG
|
||||
else
|
||||
echo "Config file not found at $CONFIG"
|
||||
echo "Starting installation session"
|
||||
./nodebb "${NODEBB_INIT_VERB}" --config=$CONFIG
|
||||
fi
|
||||
@@ -1 +0,0 @@
|
||||
db.createUser( { user: 'nodebb', pwd: 'nodebb', roles: [ { role: 'readWrite', db: 'nodebb' }, { role: 'clusterMonitor', db: 'admin' } ] } )
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"mongo": {
|
||||
"host": "mongo",
|
||||
"port": 27017,
|
||||
"database": "nodebb",
|
||||
"username": "nodebb",
|
||||
"password": "nodebb"
|
||||
},
|
||||
"redis": {
|
||||
"host": "redis",
|
||||
"port": 6379,
|
||||
"database": 0
|
||||
},
|
||||
"postgres": {
|
||||
"host": "postgres",
|
||||
"port": 5432,
|
||||
"database": "nodebb",
|
||||
"username": "nodebb",
|
||||
"password": "nodebb"
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPL-3.0",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "3.5.1",
|
||||
"homepage": "https://www.nodebb.org",
|
||||
"version": "1.15.3-beta.0",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/NodeBB/NodeBB/"
|
||||
@@ -11,8 +11,8 @@
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"start": "node loader.js",
|
||||
"lint": "eslint --cache ./nodebb .",
|
||||
"test": "nyc --reporter=html --reporter=text-summary mocha",
|
||||
"lint": "npx eslint --cache ./nodebb .",
|
||||
"test": "npx nyc --reporter=html --reporter=text-summary npx mocha",
|
||||
"coverage": "nyc report --reporter=text-lcov > ./coverage/lcov.info",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls && rm -r coverage"
|
||||
},
|
||||
@@ -22,168 +22,166 @@
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npx lint-staged",
|
||||
"commit-msg": "npx commitlint -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"eslint --fix"
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@adactive/bootstrap-tagsinput": "0.8.2",
|
||||
"@fontsource/inter": "5.0.15",
|
||||
"@fontsource/poppins": "5.0.8",
|
||||
"@fortawesome/fontawesome-free": "6.4.2",
|
||||
"@isaacs/ttlcache": "1.4.1",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"ace-builds": "1.31.2",
|
||||
"archiver": "6.0.1",
|
||||
"async": "3.2.5",
|
||||
"autoprefixer": "10.4.16",
|
||||
"@adactive/bootstrap-tagsinput": "^0.8.2",
|
||||
"ace-builds": "^1.4.9",
|
||||
"archiver": "^5.0.0",
|
||||
"async": "^3.2.0",
|
||||
"autoprefixer": "^10.0.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"benchpressjs": "2.5.1",
|
||||
"body-parser": "1.20.2",
|
||||
"bootbox": "6.0.0",
|
||||
"bootstrap": "5.3.2",
|
||||
"bootswatch": "5.3.2",
|
||||
"chalk": "4.1.2",
|
||||
"chart.js": "4.4.0",
|
||||
"cli-graph": "3.2.2",
|
||||
"clipboard": "2.0.11",
|
||||
"colors": "1.4.0",
|
||||
"commander": "11.1.0",
|
||||
"compare-versions": "6.1.0",
|
||||
"compression": "1.7.4",
|
||||
"connect-flash": "0.1.1",
|
||||
"connect-mongo": "5.1.0",
|
||||
"connect-multiparty": "2.2.0",
|
||||
"connect-pg-simple": "9.0.1",
|
||||
"connect-redis": "7.1.0",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cron": "3.1.6",
|
||||
"cropperjs": "1.6.1",
|
||||
"csrf-sync": "4.0.1",
|
||||
"daemon": "1.1.0",
|
||||
"diff": "5.1.0",
|
||||
"esbuild": "0.19.5",
|
||||
"express": "4.18.2",
|
||||
"express-session": "1.17.3",
|
||||
"express-useragent": "1.0.15",
|
||||
"file-loader": "6.2.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"graceful-fs": "4.2.11",
|
||||
"helmet": "7.1.0",
|
||||
"html-to-text": "9.0.5",
|
||||
"imagesloaded": "5.0.0",
|
||||
"ipaddr.js": "2.1.0",
|
||||
"jquery": "3.7.1",
|
||||
"jquery-deserialize": "2.0.0",
|
||||
"benchpressjs": "2.2.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"bootbox": "4.4.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"chart.js": "^2.9.3",
|
||||
"cli-graph": "^3.2.2",
|
||||
"clipboard": "^2.0.6",
|
||||
"colors": "^1.4.0",
|
||||
"commander": "^6.0.0",
|
||||
"compare-versions": "3.6.0",
|
||||
"compression": "^1.7.4",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"connect-flash": "^0.1.1",
|
||||
"connect-mongo": "3.2.0",
|
||||
"connect-multiparty": "^2.2.0",
|
||||
"connect-pg-simple": "^6.1.0",
|
||||
"connect-redis": "5.0.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cron": "^1.8.2",
|
||||
"cropperjs": "^1.5.6",
|
||||
"csurf": "^1.11.0",
|
||||
"daemon": "^1.1.0",
|
||||
"diff": "^5.0.0",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.0",
|
||||
"express-useragent": "^1.0.13",
|
||||
"graceful-fs": "^4.2.3",
|
||||
"helmet": "^4.0.0",
|
||||
"html-to-text": "^5.1.1",
|
||||
"ipaddr.js": "^2.0.0",
|
||||
"jquery": "3.5.1",
|
||||
"jquery-deserialize": "2.0.0-rc1",
|
||||
"jquery-form": "4.3.0",
|
||||
"jquery-serializeobject": "1.0.0",
|
||||
"jquery-ui": "1.13.2",
|
||||
"jquery-ui": "1.12.1",
|
||||
"jsesc": "3.0.2",
|
||||
"json2csv": "5.0.7",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"lodash": "4.17.21",
|
||||
"logrotate-stream": "0.2.9",
|
||||
"lru-cache": "10.0.2",
|
||||
"mime": "3.0.0",
|
||||
"mkdirp": "3.0.1",
|
||||
"mongodb": "6.3.0",
|
||||
"morgan": "1.10.0",
|
||||
"mousetrap": "1.6.5",
|
||||
"multiparty": "4.2.3",
|
||||
"nconf": "0.12.1",
|
||||
"nodebb-plugin-2factor": "7.4.0",
|
||||
"nodebb-plugin-composer-default": "10.2.27",
|
||||
"nodebb-plugin-dbsearch": "6.2.3",
|
||||
"nodebb-plugin-emoji": "5.1.13",
|
||||
"nodebb-plugin-emoji-android": "4.0.0",
|
||||
"nodebb-plugin-markdown": "12.2.5",
|
||||
"nodebb-plugin-mentions": "4.3.7",
|
||||
"nodebb-plugin-ntfy": "1.7.3",
|
||||
"nodebb-plugin-spam-be-gone": "2.2.0",
|
||||
"nodebb-rewards-essentials": "1.0.0",
|
||||
"nodebb-theme-harmony": "1.1.99",
|
||||
"nodebb-theme-lavender": "7.1.5",
|
||||
"nodebb-theme-peace": "2.1.25",
|
||||
"nodebb-theme-persona": "13.2.47",
|
||||
"nodebb-widget-essentials": "7.0.14",
|
||||
"nodemailer": "6.9.7",
|
||||
"json2csv": "5.0.5",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"less": "^3.11.1",
|
||||
"lodash": "^4.17.15",
|
||||
"logrotate-stream": "^0.2.6",
|
||||
"lru-cache": "6.0.0",
|
||||
"material-design-lite": "^1.3.0",
|
||||
"mime": "^2.4.4",
|
||||
"mkdirp": "^1.0.4",
|
||||
"mongodb": "3.6.3",
|
||||
"morgan": "^1.10.0",
|
||||
"mousetrap": "^1.6.5",
|
||||
"@nodebb/bootswatch": "3.4.2",
|
||||
"@nodebb/mubsub": "1.7.1",
|
||||
"@nodebb/socket.io-adapter-mongo": "3.1.1",
|
||||
"nconf": "^0.10.0",
|
||||
"nodebb-plugin-composer-default": "6.4.7",
|
||||
"nodebb-plugin-dbsearch": "4.1.2",
|
||||
"nodebb-plugin-emoji": "^3.3.0",
|
||||
"nodebb-plugin-emoji-android": "2.0.0",
|
||||
"nodebb-plugin-markdown": "8.12.1",
|
||||
"nodebb-plugin-mentions": "2.13.5",
|
||||
"nodebb-plugin-soundpack-default": "1.0.0",
|
||||
"nodebb-plugin-spam-be-gone": "0.7.6",
|
||||
"nodebb-rewards-essentials": "0.1.4",
|
||||
"nodebb-theme-lavender": "5.0.14",
|
||||
"nodebb-theme-persona": "10.2.81",
|
||||
"nodebb-theme-slick": "1.3.3",
|
||||
"nodebb-theme-vanilla": "11.3.4",
|
||||
"nodebb-widget-essentials": "4.1.2",
|
||||
"nodemailer": "^6.4.6",
|
||||
"nprogress": "0.2.0",
|
||||
"passport": "0.6.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport": "^0.4.1",
|
||||
"passport-http-bearer": "^1.0.1",
|
||||
"passport-local": "1.0.0",
|
||||
"pg": "8.11.3",
|
||||
"pg-cursor": "2.10.3",
|
||||
"postcss": "8.4.31",
|
||||
"postcss-clean": "1.2.0",
|
||||
"progress-webpack-plugin": "1.0.16",
|
||||
"prompt": "1.3.0",
|
||||
"ioredis": "5.3.2",
|
||||
"pg": "^8.0.2",
|
||||
"pg-cursor": "^2.1.9",
|
||||
"postcss": "8.1.7",
|
||||
"postcss-clean": "1.1.0",
|
||||
"promise-polyfill": "^8.1.3",
|
||||
"prompt": "^1.0.0",
|
||||
"redis": "3.0.2",
|
||||
"request": "2.88.2",
|
||||
"request-promise-native": "1.0.9",
|
||||
"rimraf": "5.0.5",
|
||||
"rss": "1.2.2",
|
||||
"rtlcss": "4.1.1",
|
||||
"sanitize-html": "2.11.0",
|
||||
"sass": "1.69.5",
|
||||
"semver": "7.5.4",
|
||||
"serve-favicon": "2.5.0",
|
||||
"sharp": "0.32.6",
|
||||
"sitemap": "7.1.1",
|
||||
"socket.io": "4.7.2",
|
||||
"socket.io-client": "4.7.2",
|
||||
"@socket.io/redis-adapter": "8.2.1",
|
||||
"sortablejs": "1.15.0",
|
||||
"spdx-license-list": "6.8.0",
|
||||
"spider-detector": "2.0.1",
|
||||
"terser-webpack-plugin": "5.3.9",
|
||||
"textcomplete": "0.18.2",
|
||||
"textcomplete.contenteditable": "0.1.1",
|
||||
"timeago": "1.6.7",
|
||||
"request-promise-native": "^1.0.8",
|
||||
"requirejs": "2.3.6",
|
||||
"rimraf": "3.0.2",
|
||||
"rss": "^1.2.2",
|
||||
"sanitize-html": "^2.0.0",
|
||||
"semver": "^7.2.1",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"sharp": "0.26.3",
|
||||
"sitemap": "^6.1.0",
|
||||
"slideout": "1.0.1",
|
||||
"socket.io": "2.3.0",
|
||||
"socket.io-adapter-cluster": "^1.0.1",
|
||||
"socket.io-adapter-postgres": "^1.2.1",
|
||||
"socket.io-client": "2.3.1",
|
||||
"socket.io-redis": "5.4.0",
|
||||
"socketio-wildcard": "2.0.0",
|
||||
"sortablejs": "1.10.2",
|
||||
"spdx-license-list": "^6.1.0",
|
||||
"spider-detector": "2.0.0",
|
||||
"textcomplete": "^0.17.1",
|
||||
"textcomplete.contenteditable": "^0.1.1",
|
||||
"timeago": "^1.6.7",
|
||||
"tinycon": "0.6.8",
|
||||
"toobusy-js": "0.5.1",
|
||||
"validator": "13.11.0",
|
||||
"webpack": "5.89.0",
|
||||
"webpack-merge": "5.10.0",
|
||||
"winston": "3.11.0",
|
||||
"workerpool": "8.0.0",
|
||||
"xml": "1.0.1",
|
||||
"xregexp": "5.1.1",
|
||||
"yargs": "17.7.2",
|
||||
"zxcvbn": "4.4.2"
|
||||
"toobusy-js": "^0.5.1",
|
||||
"uglify-es": "^3.3.9",
|
||||
"validator": "13.1.17",
|
||||
"visibilityjs": "2.0.2",
|
||||
"winston": "3.3.3",
|
||||
"xml": "^1.0.1",
|
||||
"xregexp": "^4.3.0",
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-parser": "10.1.0",
|
||||
"@commitlint/cli": "18.4.2",
|
||||
"@commitlint/config-angular": "18.4.2",
|
||||
"coveralls": "3.1.1",
|
||||
"eslint": "8.54.0",
|
||||
"eslint-config-nodebb": "0.2.1",
|
||||
"eslint-plugin-import": "2.29.0",
|
||||
"grunt": "1.6.1",
|
||||
"@apidevtools/swagger-parser": "10.0.2",
|
||||
"@commitlint/cli": "11.0.0",
|
||||
"@commitlint/config-angular": "11.0.0",
|
||||
"coveralls": "3.1.0",
|
||||
"eslint": "7.13.0",
|
||||
"eslint-config-airbnb-base": "14.2.1",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"grunt": "1.3.0",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"husky": "8.0.3",
|
||||
"jsdom": "22.1.0",
|
||||
"lint-staged": "15.1.0",
|
||||
"mocha": "10.2.0",
|
||||
"husky": "4.3.0",
|
||||
"jsdom": "16.4.0",
|
||||
"lint-staged": "10.5.1",
|
||||
"mocha": "8.2.1",
|
||||
"mocha-lcov-reporter": "1.3.0",
|
||||
"mockdate": "3.0.5",
|
||||
"nyc": "15.1.0",
|
||||
"smtp-server": "3.13.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"sass-embedded": "1.69.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"*/jquery": "3.7.1"
|
||||
"smtp-server": "3.8.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/NodeBB/NodeBB/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=10"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Andrew Rodrigues",
|
||||
"email": "andrew@nodebb.org",
|
||||
"url": "https://github.com/psychobunny"
|
||||
},
|
||||
{
|
||||
"name": "Julian Lam",
|
||||
"email": "julian@nodebb.org",
|
||||
@@ -195,4 +193,4 @@
|
||||
"url": "https://github.com/barisusakli"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
206
install/web.js
206
install/web.js
@@ -6,14 +6,17 @@ const bodyParser = require('body-parser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const less = require('less');
|
||||
const util = require('util');
|
||||
const lessRenderAsync = util.promisify(
|
||||
(style, opts, cb) => less.render(String(style), opts, cb)
|
||||
);
|
||||
const uglify = require('uglify-es');
|
||||
const nconf = require('nconf');
|
||||
|
||||
const Benchpress = require('benchpressjs');
|
||||
const { mkdirp } = require('mkdirp');
|
||||
const mkdirp = require('mkdirp');
|
||||
const { paths } = require('../src/constants');
|
||||
const sass = require('../src/utils').getSass();
|
||||
|
||||
const app = express();
|
||||
let server;
|
||||
@@ -23,8 +26,8 @@ const formats = [
|
||||
];
|
||||
|
||||
const timestampFormat = winston.format((info) => {
|
||||
const dateString = `${new Date().toISOString()} [${global.process.pid}]`;
|
||||
info.level = `${dateString} - ${info.level}`;
|
||||
var dateString = new Date().toISOString() + ' [' + global.process.pid + ']';
|
||||
info.level = dateString + ' - ' + info.level;
|
||||
return info;
|
||||
});
|
||||
formats.push(timestampFormat());
|
||||
@@ -46,24 +49,29 @@ winston.configure({
|
||||
});
|
||||
|
||||
const web = module.exports;
|
||||
|
||||
const scripts = [
|
||||
'node_modules/jquery/dist/jquery.js',
|
||||
'node_modules/xregexp/xregexp-all.js',
|
||||
'public/src/modules/slugify.js',
|
||||
'public/src/utils.js',
|
||||
'public/src/installer/install.js',
|
||||
'node_modules/zxcvbn/dist/zxcvbn.js',
|
||||
];
|
||||
|
||||
let installing = false;
|
||||
let success = false;
|
||||
let error = false;
|
||||
let launchUrl;
|
||||
let timeStart = 0;
|
||||
const totalTime = 1000 * 60 * 3;
|
||||
|
||||
|
||||
const viewsDir = path.join(paths.baseDir, 'build/public/templates');
|
||||
|
||||
web.install = async function (port) {
|
||||
port = port || 4567;
|
||||
winston.info(`Launching web installer on port ${port}`);
|
||||
winston.info('Launching web installer on port ' + port);
|
||||
|
||||
app.use(express.static('public', {}));
|
||||
app.use('/assets', express.static(path.join(__dirname, '../build/public'), {}));
|
||||
|
||||
app.engine('tpl', (filepath, options, callback) => {
|
||||
app.engine('tpl', function (filepath, options, callback) {
|
||||
filepath = filepath.replace(/\.tpl$/, '.js');
|
||||
|
||||
Benchpress.__express(filepath, options, callback);
|
||||
@@ -76,8 +84,8 @@ web.install = async function (port) {
|
||||
try {
|
||||
await Promise.all([
|
||||
compileTemplate(),
|
||||
compileSass(),
|
||||
runWebpack(),
|
||||
compileLess(),
|
||||
compileJS(),
|
||||
copyCSS(),
|
||||
loadDefaults(),
|
||||
]);
|
||||
@@ -88,16 +96,9 @@ web.install = async function (port) {
|
||||
}
|
||||
};
|
||||
|
||||
async function runWebpack() {
|
||||
const util = require('util');
|
||||
const webpackCfg = require('../webpack.installer');
|
||||
const compiler = webpack(webpackCfg);
|
||||
const webpackRun = util.promisify(compiler.run).bind(compiler);
|
||||
await webpackRun();
|
||||
}
|
||||
|
||||
function launchExpress(port) {
|
||||
server = app.listen(port, () => {
|
||||
server = app.listen(port, function () {
|
||||
winston.info('Web installer listening on http://%s:%s', '0.0.0.0', port);
|
||||
});
|
||||
}
|
||||
@@ -105,40 +106,21 @@ function launchExpress(port) {
|
||||
function setupRoutes() {
|
||||
app.get('/', welcome);
|
||||
app.post('/', install);
|
||||
app.get('/testdb', testDatabase);
|
||||
app.post('/launch', launch);
|
||||
app.get('/ping', ping);
|
||||
app.get('/sping', ping);
|
||||
}
|
||||
|
||||
async function testDatabase(req, res) {
|
||||
let db;
|
||||
try {
|
||||
const keys = Object.keys(req.query);
|
||||
const dbName = keys[0].split(':')[0];
|
||||
db = require(`../src/database/${dbName}`);
|
||||
|
||||
const opts = {};
|
||||
keys.forEach((key) => {
|
||||
opts[key.replace(`${dbName}:`, '')] = req.query[key];
|
||||
});
|
||||
|
||||
await db.init(opts);
|
||||
const global = await db.getObject('global');
|
||||
await db.close();
|
||||
res.json({ success: 1, dbfull: !!global });
|
||||
} catch (err) {
|
||||
res.json({ error: err.stack });
|
||||
}
|
||||
}
|
||||
|
||||
function ping(req, res) {
|
||||
res.status(200).send(req.path === '/sping' ? 'healthy' : '200');
|
||||
}
|
||||
|
||||
function welcome(req, res) {
|
||||
const dbs = ['mongo', 'redis', 'postgres'];
|
||||
const databases = dbs.map((databaseName) => {
|
||||
const questions = require(`../src/database/${databaseName}`).questions.filter(question => question && !question.hideOnWebInstall);
|
||||
var dbs = ['redis', 'mongo', 'postgres'];
|
||||
var databases = dbs.map(function (databaseName) {
|
||||
var questions = require('../src/database/' + databaseName).questions.filter(function (question) {
|
||||
return question && !question.hideOnWebInstall;
|
||||
});
|
||||
|
||||
return {
|
||||
name: databaseName,
|
||||
@@ -146,9 +128,10 @@ function welcome(req, res) {
|
||||
};
|
||||
});
|
||||
|
||||
const defaults = require('./data/defaults.json');
|
||||
var defaults = require('./data/defaults');
|
||||
|
||||
res.render('install/index', {
|
||||
url: nconf.get('url') || (`${req.protocol}://${req.get('host')}`),
|
||||
url: nconf.get('url') || (req.protocol + '://' + req.get('host')),
|
||||
launchUrl: launchUrl,
|
||||
skipGeneralSetup: !!nconf.get('url'),
|
||||
databases: databases,
|
||||
@@ -159,7 +142,6 @@ function welcome(req, res) {
|
||||
minimumPasswordLength: defaults.minimumPasswordLength,
|
||||
minimumPasswordStrength: defaults.minimumPasswordStrength,
|
||||
installing: installing,
|
||||
percentInstalled: installing ? ((Date.now() - timeStart) / totalTime * 100).toFixed(2) : 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -167,53 +149,51 @@ function install(req, res) {
|
||||
if (installing) {
|
||||
return welcome(req, res);
|
||||
}
|
||||
timeStart = Date.now();
|
||||
req.setTimeout(0);
|
||||
installing = true;
|
||||
var setupEnvVars = nconf.get();
|
||||
for (var i in req.body) {
|
||||
if (req.body.hasOwnProperty(i) && !process.env.hasOwnProperty(i)) {
|
||||
setupEnvVars[i.replace(':', '__')] = req.body[i];
|
||||
}
|
||||
}
|
||||
|
||||
const database = nconf.get('database') || req.body.database || 'mongo';
|
||||
const setupEnvVars = {
|
||||
...process.env,
|
||||
CONFIG: nconf.get('config'),
|
||||
NODEBB_CONFIG: nconf.get('config'),
|
||||
NODEBB_URL: nconf.get('url') || req.body.url || (`${req.protocol}://${req.get('host')}`),
|
||||
NODEBB_PORT: nconf.get('port') || 4567,
|
||||
NODEBB_ADMIN_USERNAME: nconf.get('admin:username') || req.body['admin:username'],
|
||||
NODEBB_ADMIN_PASSWORD: nconf.get('admin:password') || req.body['admin:password'],
|
||||
NODEBB_ADMIN_EMAIL: nconf.get('admin:email') || req.body['admin:email'],
|
||||
NODEBB_DB: database,
|
||||
NODEBB_DB_HOST: nconf.get(`${database}:host`) || req.body[`${database}:host`],
|
||||
NODEBB_DB_PORT: nconf.get(`${database}:port`) || req.body[`${database}:port`],
|
||||
NODEBB_DB_USER: nconf.get(`${database}:username`) || req.body[`${database}:username`],
|
||||
NODEBB_DB_PASSWORD: nconf.get(`${database}:password`) || req.body[`${database}:password`],
|
||||
NODEBB_DB_NAME: nconf.get(`${database}:database`) || req.body[`${database}:database`],
|
||||
NODEBB_DB_SSL: nconf.get(`${database}:ssl`) || req.body[`${database}:ssl`],
|
||||
defaultPlugins: JSON.stringify(nconf.get('defaultplugins') || nconf.get('defaultPlugins') || []),
|
||||
// Flatten any objects in setupEnvVars
|
||||
const pushToRoot = function (parentKey, key) {
|
||||
setupEnvVars[parentKey + '__' + key] = setupEnvVars[parentKey][key];
|
||||
};
|
||||
for (var j in setupEnvVars) {
|
||||
if (setupEnvVars.hasOwnProperty(j) && typeof setupEnvVars[j] === 'object' && setupEnvVars[j] !== null && !Array.isArray(setupEnvVars[j])) {
|
||||
Object.keys(setupEnvVars[j]).forEach(pushToRoot.bind(null, j));
|
||||
delete setupEnvVars[j];
|
||||
} else if (Array.isArray(setupEnvVars[j])) {
|
||||
setupEnvVars[j] = JSON.stringify(setupEnvVars[j]);
|
||||
}
|
||||
}
|
||||
|
||||
winston.info('Starting setup process');
|
||||
launchUrl = setupEnvVars.NODEBB_URL;
|
||||
winston.info(setupEnvVars);
|
||||
launchUrl = setupEnvVars.url;
|
||||
|
||||
const child = require('child_process').fork('app', ['--setup'], {
|
||||
var child = require('child_process').fork('app', ['--setup'], {
|
||||
env: setupEnvVars,
|
||||
});
|
||||
child.on('error', (err) => {
|
||||
error = true;
|
||||
success = false;
|
||||
winston.error(err.stack);
|
||||
});
|
||||
child.on('close', (data) => {
|
||||
|
||||
child.on('close', function (data) {
|
||||
installing = false;
|
||||
success = data === 0;
|
||||
error = data !== 0;
|
||||
launch();
|
||||
|
||||
welcome(req, res);
|
||||
});
|
||||
welcome(req, res);
|
||||
}
|
||||
|
||||
async function launch() {
|
||||
async function launch(req, res) {
|
||||
try {
|
||||
res.json({});
|
||||
server.close();
|
||||
let child;
|
||||
req.setTimeout(0);
|
||||
var child;
|
||||
|
||||
if (!nconf.get('launchCmd')) {
|
||||
child = childProcess.spawn('node', ['loader.js'], {
|
||||
@@ -234,20 +214,15 @@ async function launch() {
|
||||
}
|
||||
|
||||
const filesToDelete = [
|
||||
path.join(__dirname, '../public', 'installer.css'),
|
||||
path.join(__dirname, '../public', 'bootstrap.min.css'),
|
||||
path.join(__dirname, '../build/public', 'installer.min.js'),
|
||||
'installer.css',
|
||||
'installer.min.js',
|
||||
'bootstrap.min.css',
|
||||
];
|
||||
try {
|
||||
await Promise.all(
|
||||
filesToDelete.map(
|
||||
filename => fs.promises.unlink(filename)
|
||||
)
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
filesToDelete.map(
|
||||
filename => fs.promises.unlink(path.join(__dirname, '../public', filename))
|
||||
)
|
||||
);
|
||||
child.unref();
|
||||
process.exit(0);
|
||||
} catch (err) {
|
||||
@@ -275,42 +250,51 @@ async function compileTemplate() {
|
||||
]);
|
||||
}
|
||||
|
||||
async function compileSass() {
|
||||
async function compileLess() {
|
||||
try {
|
||||
const installSrc = path.join(__dirname, '../public/scss/install.scss');
|
||||
const installSrc = path.join(__dirname, '../public/less/install.less');
|
||||
const style = await fs.promises.readFile(installSrc);
|
||||
const scssOutput = sass.compileString(String(style), {
|
||||
loadPaths: [
|
||||
path.join(__dirname, '../public/scss'),
|
||||
],
|
||||
});
|
||||
|
||||
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), scssOutput.css.toString());
|
||||
const css = await lessRenderAsync(style, { filename: path.resolve(installSrc) });
|
||||
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), css.css);
|
||||
} catch (err) {
|
||||
winston.error(`Unable to compile SASS: \n${err.stack}`);
|
||||
winston.error('Unable to compile LESS: \n' + err.stack);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function compileJS() {
|
||||
let code = '';
|
||||
|
||||
for (const srcPath of scripts) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const buffer = await fs.promises.readFile(path.join(__dirname, '..', srcPath));
|
||||
code += buffer.toString();
|
||||
}
|
||||
const minified = uglify.minify(code, {
|
||||
compress: false,
|
||||
});
|
||||
if (!minified.code) {
|
||||
throw new Error('[[error:failed-to-minify]]');
|
||||
}
|
||||
await fs.promises.writeFile(path.join(__dirname, '../public/installer.min.js'), minified.code);
|
||||
}
|
||||
|
||||
async function copyCSS() {
|
||||
await fs.promises.copyFile(
|
||||
path.join(__dirname, '../node_modules/bootstrap/dist/css/bootstrap.min.css'),
|
||||
path.join(__dirname, '../public/bootstrap.min.css'),
|
||||
const src = await fs.promises.readFile(
|
||||
path.join(__dirname, '../node_modules/bootstrap/dist/css/bootstrap.min.css'), 'utf8'
|
||||
);
|
||||
await fs.promises.writeFile(path.join(__dirname, '../public/bootstrap.min.css'), src);
|
||||
}
|
||||
|
||||
async function loadDefaults() {
|
||||
const setupDefaultsPath = path.join(__dirname, '../setup.json');
|
||||
try {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
await fs.promises.access(setupDefaultsPath, fs.constants.F_OK | fs.constants.R_OK);
|
||||
} catch (err) {
|
||||
// setup.json not found or inaccessible, proceed with no defaults
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
winston.info('[installer] Found setup.json, populating default values');
|
||||
nconf.file({
|
||||
|
||||
155
loader.js
155
loader.js
@@ -1,61 +1,82 @@
|
||||
'use strict';
|
||||
|
||||
const nconf = require('nconf');
|
||||
const fs = require('fs');
|
||||
const url = require('url');
|
||||
const path = require('path');
|
||||
const { fork } = require('child_process');
|
||||
const logrotate = require('logrotate-stream');
|
||||
const { mkdirp } = require('mkdirp');
|
||||
var nconf = require('nconf');
|
||||
var fs = require('fs');
|
||||
var url = require('url');
|
||||
var path = require('path');
|
||||
var fork = require('child_process').fork;
|
||||
var async = require('async');
|
||||
var logrotate = require('logrotate-stream');
|
||||
var mkdirp = require('mkdirp');
|
||||
|
||||
const file = require('./src/file');
|
||||
const pkg = require('./package.json');
|
||||
var file = require('./src/file');
|
||||
var pkg = require('./package.json');
|
||||
|
||||
const pathToConfig = path.resolve(__dirname, process.env.CONFIG || 'config.json');
|
||||
var pathToConfig = path.resolve(__dirname, process.env.CONFIG || 'config.json');
|
||||
|
||||
nconf.argv().env().file({
|
||||
file: pathToConfig,
|
||||
});
|
||||
|
||||
const pidFilePath = path.join(__dirname, 'pidfile');
|
||||
var pidFilePath = path.join(__dirname, 'pidfile');
|
||||
|
||||
const outputLogFilePath = path.join(__dirname, nconf.get('logFile') || 'logs/output.log');
|
||||
var outputLogFilePath = path.join(__dirname, nconf.get('logFile') || 'logs/output.log');
|
||||
|
||||
const logDir = path.dirname(outputLogFilePath);
|
||||
var logDir = path.dirname(outputLogFilePath);
|
||||
if (!fs.existsSync(logDir)) {
|
||||
mkdirp.sync(path.dirname(outputLogFilePath));
|
||||
}
|
||||
|
||||
const output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
||||
const silent = nconf.get('silent') === 'false' ? false : nconf.get('silent') !== false;
|
||||
let numProcs;
|
||||
const workers = [];
|
||||
const Loader = {};
|
||||
const appPath = path.join(__dirname, 'app.js');
|
||||
var output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
||||
var silent = nconf.get('silent') === 'false' ? false : nconf.get('silent') !== false;
|
||||
var numProcs;
|
||||
var workers = [];
|
||||
var Loader = {
|
||||
timesStarted: 0,
|
||||
};
|
||||
var appPath = path.join(__dirname, 'app.js');
|
||||
|
||||
Loader.init = function () {
|
||||
Loader.init = function (callback) {
|
||||
if (silent) {
|
||||
console.log = (...args) => {
|
||||
output.write(`${args.join(' ')}\n`);
|
||||
console.log = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
output.write(args.join(' ') + '\n');
|
||||
};
|
||||
}
|
||||
|
||||
process.on('SIGHUP', Loader.restart);
|
||||
process.on('SIGTERM', Loader.stop);
|
||||
callback();
|
||||
};
|
||||
|
||||
Loader.displayStartupMessages = function () {
|
||||
Loader.displayStartupMessages = function (callback) {
|
||||
console.log('');
|
||||
console.log(`NodeBB v${pkg.version} Copyright (C) 2013-${(new Date()).getFullYear()} NodeBB Inc.`);
|
||||
console.log('NodeBB v' + pkg.version + ' Copyright (C) 2013-2014 NodeBB Inc.');
|
||||
console.log('This program comes with ABSOLUTELY NO WARRANTY.');
|
||||
console.log('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
console.log('For the full license, please visit: http://www.gnu.org/copyleft/gpl.html');
|
||||
console.log('');
|
||||
callback();
|
||||
};
|
||||
|
||||
Loader.addWorkerEvents = function (worker) {
|
||||
worker.on('exit', (code, signal) => {
|
||||
console.log(`[cluster] Child Process (${worker.pid}) has exited (code: ${code}, signal: ${signal})`);
|
||||
worker.on('exit', function (code, signal) {
|
||||
if (code !== 0) {
|
||||
if (Loader.timesStarted < numProcs * 3) {
|
||||
Loader.timesStarted += 1;
|
||||
if (Loader.crashTimer) {
|
||||
clearTimeout(Loader.crashTimer);
|
||||
}
|
||||
Loader.crashTimer = setTimeout(function () {
|
||||
Loader.timesStarted = 0;
|
||||
}, 10000);
|
||||
} else {
|
||||
console.log((numProcs * 3) + ' restarts in 10 seconds, most likely an error on startup. Halting.');
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[cluster] Child Process (' + worker.pid + ') has exited (code: ' + code + ', signal: ' + signal + ')');
|
||||
if (!(worker.suicide || code === 0)) {
|
||||
console.log('[cluster] Spinning up another process...');
|
||||
|
||||
@@ -63,7 +84,7 @@ Loader.addWorkerEvents = function (worker) {
|
||||
}
|
||||
});
|
||||
|
||||
worker.on('message', (message) => {
|
||||
worker.on('message', function (message) {
|
||||
if (message && typeof message === 'object' && message.action) {
|
||||
switch (message.action) {
|
||||
case 'restart':
|
||||
@@ -71,12 +92,12 @@ Loader.addWorkerEvents = function (worker) {
|
||||
Loader.restart();
|
||||
break;
|
||||
case 'pubsub':
|
||||
workers.forEach((w) => {
|
||||
workers.forEach(function (w) {
|
||||
w.send(message);
|
||||
});
|
||||
break;
|
||||
case 'socket.io':
|
||||
workers.forEach((w) => {
|
||||
workers.forEach(function (w) {
|
||||
if (w !== worker) {
|
||||
w.send(message);
|
||||
}
|
||||
@@ -87,28 +108,32 @@ Loader.addWorkerEvents = function (worker) {
|
||||
});
|
||||
};
|
||||
|
||||
Loader.start = function () {
|
||||
Loader.start = function (callback) {
|
||||
numProcs = getPorts().length;
|
||||
console.log(`Clustering enabled: Spinning up ${numProcs} process(es).\n`);
|
||||
console.log('Clustering enabled: Spinning up ' + numProcs + ' process(es).\n');
|
||||
|
||||
for (let x = 0; x < numProcs; x += 1) {
|
||||
for (var x = 0; x < numProcs; x += 1) {
|
||||
forkWorker(x, x === 0);
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
function forkWorker(index, isPrimary) {
|
||||
const ports = getPorts();
|
||||
const args = [];
|
||||
var ports = getPorts();
|
||||
var args = [];
|
||||
|
||||
if (!ports[index]) {
|
||||
return console.log(`[cluster] invalid port for worker : ${index} ports: ${ports.length}`);
|
||||
return console.log('[cluster] invalid port for worker : ' + index + ' ports: ' + ports.length);
|
||||
}
|
||||
|
||||
process.env.isPrimary = isPrimary;
|
||||
process.env.isCluster = nconf.get('isCluster') || ports.length > 1;
|
||||
process.env.port = ports[index];
|
||||
|
||||
const worker = fork(appPath, args, {
|
||||
var worker = fork(appPath, args, {
|
||||
silent: silent,
|
||||
env: process.env,
|
||||
});
|
||||
@@ -121,20 +146,20 @@ function forkWorker(index, isPrimary) {
|
||||
Loader.addWorkerEvents(worker);
|
||||
|
||||
if (silent) {
|
||||
const output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
||||
var output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
||||
worker.stdout.pipe(output);
|
||||
worker.stderr.pipe(output);
|
||||
}
|
||||
}
|
||||
|
||||
function getPorts() {
|
||||
const _url = nconf.get('url');
|
||||
var _url = nconf.get('url');
|
||||
if (!_url) {
|
||||
console.log('[cluster] url is undefined, please check your config.json');
|
||||
process.exit();
|
||||
}
|
||||
const urlObject = url.parse(_url);
|
||||
let port = nconf.get('PORT') || nconf.get('port') || urlObject.port || 4567;
|
||||
var urlObject = url.parse(_url);
|
||||
var port = nconf.get('PORT') || nconf.get('port') || urlObject.port || 4567;
|
||||
if (!Array.isArray(port)) {
|
||||
port = [port];
|
||||
}
|
||||
@@ -147,13 +172,13 @@ Loader.restart = function () {
|
||||
nconf.remove('file');
|
||||
nconf.use('file', { file: pathToConfig });
|
||||
|
||||
fs.readFile(pathToConfig, { encoding: 'utf-8' }, (err, configFile) => {
|
||||
fs.readFile(pathToConfig, { encoding: 'utf-8' }, function (err, configFile) {
|
||||
if (err) {
|
||||
console.error('Error reading config');
|
||||
throw err;
|
||||
}
|
||||
|
||||
const conf = JSON.parse(configFile);
|
||||
var conf = JSON.parse(configFile);
|
||||
|
||||
nconf.stores.env.readOnly = false;
|
||||
nconf.set('url', conf.url);
|
||||
@@ -176,13 +201,13 @@ Loader.stop = function () {
|
||||
};
|
||||
|
||||
function killWorkers() {
|
||||
workers.forEach((worker) => {
|
||||
workers.forEach(function (worker) {
|
||||
worker.suicide = true;
|
||||
worker.kill();
|
||||
});
|
||||
}
|
||||
|
||||
fs.open(pathToConfig, 'r', (err) => {
|
||||
fs.open(pathToConfig, 'r', function (err) {
|
||||
if (err) {
|
||||
// No config detected, kickstart web installer
|
||||
fork('app');
|
||||
@@ -191,25 +216,12 @@ fs.open(pathToConfig, 'r', (err) => {
|
||||
|
||||
if (nconf.get('daemon') !== 'false' && nconf.get('daemon') !== false) {
|
||||
if (file.existsSync(pidFilePath)) {
|
||||
let pid = 0;
|
||||
try {
|
||||
pid = fs.readFileSync(pidFilePath, { encoding: 'utf-8' });
|
||||
if (pid) {
|
||||
process.kill(pid, 0);
|
||||
console.info(`Process "${pid}" from pidfile already running, exiting`);
|
||||
process.exit();
|
||||
} else {
|
||||
console.info(`Invalid pid "${pid}" from pidfile, deleting pidfile`);
|
||||
fs.unlinkSync(pidFilePath);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.code === 'ESRCH') {
|
||||
console.info(`Process "${pid}" from pidfile not found, deleting pidfile`);
|
||||
fs.unlinkSync(pidFilePath);
|
||||
} else {
|
||||
console.error(err.stack);
|
||||
throw err;
|
||||
}
|
||||
var pid = fs.readFileSync(pidFilePath, { encoding: 'utf-8' });
|
||||
process.kill(pid, 0);
|
||||
process.exit();
|
||||
} catch (e) {
|
||||
fs.unlinkSync(pidFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,12 +233,15 @@ fs.open(pathToConfig, 'r', (err) => {
|
||||
|
||||
fs.writeFileSync(pidFilePath, String(process.pid));
|
||||
}
|
||||
try {
|
||||
Loader.init();
|
||||
Loader.displayStartupMessages();
|
||||
Loader.start();
|
||||
} catch (err) {
|
||||
console.error('[loader] Error during startup');
|
||||
throw err;
|
||||
}
|
||||
|
||||
async.series([
|
||||
Loader.init,
|
||||
Loader.displayStartupMessages,
|
||||
Loader.start,
|
||||
], function (err) {
|
||||
if (err) {
|
||||
console.error('[loader] Error during startup');
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,54 @@
|
||||
{
|
||||
"extends": "nodebb/public"
|
||||
"globals": {
|
||||
"app": true,
|
||||
"io": true,
|
||||
"socket": true,
|
||||
"ajaxify": true,
|
||||
"config": true,
|
||||
"utils": true,
|
||||
"overrides": true,
|
||||
"componentHandler": true,
|
||||
"bootbox": true,
|
||||
"Visibility": true,
|
||||
"Tinycon": true,
|
||||
"Promise": true
|
||||
},
|
||||
"env": {
|
||||
"jquery": true,
|
||||
"amd": true,
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"block-scoped-var": "off",
|
||||
"no-dupe-class-members": "off",
|
||||
"no-var": "off",
|
||||
"object-shorthand": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
"prefer-spread": "off",
|
||||
"prefer-object-spread": "off",
|
||||
"prefer-reflect": "off",
|
||||
"prefer-template": "off"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"classes": false,
|
||||
"defaultParams": false,
|
||||
"experimentalObjectRestSpread": false,
|
||||
"blockBindings": false,
|
||||
"forOf": false,
|
||||
"generators": false,
|
||||
"globalReturn": false,
|
||||
"jsx": false,
|
||||
"modules": false,
|
||||
"objectLiteralComputedProperties": false,
|
||||
"objectLiteralDuplicateProperties": false,
|
||||
"objectLiteralShorthandMethods": false,
|
||||
"objectLiteralShorthandProperties": false,
|
||||
"impliedStrict": false,
|
||||
"restParams": false,
|
||||
"superInFunctions": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
83
public/.jshintrc
Normal file
83
public/.jshintrc
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"maxerr" : 50, // {int} Maximum error before stopping
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"indent" : 4, // {int} Number of spaces to use for indentation
|
||||
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : false, // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : true, // true: Require all defined variables be used
|
||||
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||
"trailing" : false, // true: Prohibit trailing whitespaces
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : false, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||
// (ex: `for each`, multiple try/catch, function expression…)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
"globals": {
|
||||
"app": true,
|
||||
"io": true,
|
||||
"socket": true,
|
||||
"ajaxify": true,
|
||||
"config": true,
|
||||
"utils": true,
|
||||
"overrides": true,
|
||||
"componentHandler": true,
|
||||
"bootbox": true,
|
||||
"templates": true,
|
||||
"Visibility": true,
|
||||
"Tinycon": true,
|
||||
"require": true,
|
||||
"define": true,
|
||||
"ace": true,
|
||||
"Sortable": true,
|
||||
"Slideout": true,
|
||||
"NProgress": true
|
||||
},
|
||||
|
||||
"jquery": true,
|
||||
"browser": true
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
body {
|
||||
background: #00A9EA;
|
||||
color: white;
|
||||
/* see public/less/admin/vars.less for documentation on system font family */
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
text-align: center;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 215 KiB |
@@ -3,7 +3,7 @@
|
||||
The files here are read-only and overwritten daily (if there are changes) by the
|
||||
helper bot [Misty](https://github.com/nodebb-misty).
|
||||
|
||||
Our localisation efforts are handled via [our Transifex Project](https://explore.transifex.com/nodebb/nodebb/),
|
||||
Our localisation efforts are handled via [our Transifex Project](https://www.transifex.com/nodebb/nodebb/),
|
||||
and any pull requests made to this directory will be automatically closed because
|
||||
localisations can go out-of-sync when edited directly.
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# The files here are not meant to be edited directly
|
||||
|
||||
Please see the → [Internalization README](../README.md).
|
||||
@@ -3,16 +3,5 @@
|
||||
"alert.confirm-restart": "هل تريد بالتأكيد إعادة تشغيل NodeBB؟",
|
||||
|
||||
"acp-title": "لوحة تحكم إدارة NodeBB | %1",
|
||||
"settings-header-contents": "محتويات",
|
||||
"changes-saved": "Changes Saved",
|
||||
"changes-saved-message": "Your changes to the NodeBB configuration have been saved.",
|
||||
"changes-not-saved": "لم يتم حفظ التغييرات",
|
||||
"changes-not-saved-message": "حدثت مشكلة أثناء حفظ التغييرات في NodeBB. (%1)",
|
||||
"save-changes": "Save changes",
|
||||
"min": "Min:",
|
||||
"max": "Max:",
|
||||
"view": "View",
|
||||
"edit": "Edit",
|
||||
"add": "Add",
|
||||
"select-icon": "Select Icon"
|
||||
"settings-header-contents": "محتويات"
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"cache": "Cache",
|
||||
"post-cache": "التخزين المؤقت للمشاركات",
|
||||
"group-cache": "التخزين المؤقت للمجموعات",
|
||||
"local-cache": "تخزين مؤقت محلي",
|
||||
"object-cache": "تخزين مؤقت للأشياء",
|
||||
"percent-full": "1% كاملة",
|
||||
"post-cache-size": "حجم التخزين المؤقت للمشاركات",
|
||||
"items-in-cache": "العناصر في التخزين المؤقت"
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
{
|
||||
"x-b": "٪1 بايت",
|
||||
"x-mb": "٪1 ميقا بايت",
|
||||
"x-gb": "٪1 قيقا بايت",
|
||||
"uptime-seconds": "مدة التشغيل بالثواني",
|
||||
"uptime-days": "مدة التشغيل بالأيام",
|
||||
"x-b": "%1 b",
|
||||
"x-mb": "%1 mb",
|
||||
"x-gb": "%1 gb",
|
||||
"uptime-seconds": "Uptime in Seconds",
|
||||
"uptime-days": "Uptime in Days",
|
||||
|
||||
"mongo": "MongoDB",
|
||||
"mongo.version": "اصدار MongoDB",
|
||||
"mongo.storage-engine": "محرك التخزين",
|
||||
"mongo.collections": "التجميعات",
|
||||
"mongo.objects": "العناصر",
|
||||
"mongo.avg-object-size": "معدل حجم العناصر",
|
||||
"mongo.data-size": "حجم البيانات",
|
||||
"mongo.storage-size": "حجم التخرين",
|
||||
"mongo.index-size": "حجم الفهرس",
|
||||
"mongo.file-size": "حجم الملف",
|
||||
"mongo.resident-memory": "الذاكرة الساكنة",
|
||||
"mongo": "Mongo",
|
||||
"mongo.version": "MongoDB Version",
|
||||
"mongo.storage-engine": "Storage Engine",
|
||||
"mongo.collections": "Collections",
|
||||
"mongo.objects": "Objects",
|
||||
"mongo.avg-object-size": "Avg. Object Size",
|
||||
"mongo.data-size": "Data Size",
|
||||
"mongo.storage-size": "Storage Size",
|
||||
"mongo.index-size": "Index Size",
|
||||
"mongo.file-size": "File Size",
|
||||
"mongo.resident-memory": "Resident Memory",
|
||||
"mongo.virtual-memory": "الذاكرة الإفتراضية",
|
||||
"mongo.mapped-memory": "Mapped Memory",
|
||||
"mongo.bytes-in": "البايتات الواردة",
|
||||
"mongo.bytes-out": "البايتات الصادرة",
|
||||
"mongo.num-requests": "عدد الطلبات",
|
||||
"mongo.raw-info": "معلومات MongoDB الأولية",
|
||||
"mongo.unauthorized": "لم يستطع NodeBB من الاستعلام عن احصاءات قواعد البيانات ل MongoDB. الرجاء التأكد من أن المستخدم في NodeBB يحتوي على دور "clusterMonitor" ال "admin" لقواعد البيانات.",
|
||||
"mongo.bytes-in": "Bytes In",
|
||||
"mongo.bytes-out": "Bytes Out",
|
||||
"mongo.num-requests": "Number of Requests",
|
||||
"mongo.raw-info": "MongoDB Raw Info",
|
||||
"mongo.unauthorized": "NodeBB was unable to query the MongoDB database for relevant statistics. Please ensure that the user in use by NodeBB contains the "clusterMonitor" role for the "admin" database.",
|
||||
|
||||
"redis": "Redis",
|
||||
"redis.version": "إصدار Redis",
|
||||
"redis.keys": "المفاتيح",
|
||||
"redis.expires": "ينتهي ",
|
||||
"redis.avg-ttl": "متوسط وقت الانعاش",
|
||||
"redis.connected-clients": "العميل المتصل",
|
||||
"redis.connected-slaves": "البدلاء المتصلين",
|
||||
"redis.blocked-clients": "العملاء المحظورون",
|
||||
"redis.version": "Redis Version",
|
||||
"redis.keys": "Keys",
|
||||
"redis.expires": "Expires",
|
||||
"redis.avg-ttl": "Average TTL",
|
||||
"redis.connected-clients": "Connected Clients",
|
||||
"redis.connected-slaves": "Connected Slaves",
|
||||
"redis.blocked-clients": "Blocked Clients",
|
||||
"redis.used-memory": "الذاكرة المستخدمة",
|
||||
"redis.memory-frag-ratio": "نسبة تجزئة الذاكرة",
|
||||
"redis.memory-frag-ratio": "Memory Fragmentation Ratio",
|
||||
"redis.total-connections-recieved": "إجمالي الاتصالات المستلمة",
|
||||
"redis.total-commands-processed": "إجمالي الأوامر التي تمت معالجتها",
|
||||
"redis.iops": "العمليات اللحظية في الثانية",
|
||||
"redis.iinput": "الإدخال الفوري في الثانية",
|
||||
"redis.ioutput": "المخرجات الفورية في الثانية",
|
||||
"redis.total-input": "مجموع المدخلات",
|
||||
"redis.total-output": "مجموع المخرجات",
|
||||
"redis.iops": "Instantaneous Ops. Per Second",
|
||||
"redis.iinput": "Instantaneous Input Per Second",
|
||||
"redis.ioutput": "Instantaneous Output Per Second",
|
||||
"redis.total-input": "Total Input",
|
||||
"redis.total-output": "Total Ouput",
|
||||
|
||||
"redis.keyspace-hits": "المفاتيح المضغوطة",
|
||||
"redis.keyspace-misses": "المفاتيح المخفقة",
|
||||
"redis.raw-info": "معلومات Redis الأولية",
|
||||
"redis.keyspace-hits": "Keyspace Hits",
|
||||
"redis.keyspace-misses": "Keyspace Misses",
|
||||
"redis.raw-info": "Redis Raw Info",
|
||||
|
||||
"postgres": "Postgres",
|
||||
"postgres.version": "إصدار PostgreSQL",
|
||||
"postgres.raw-info": "معلومات Postgres الأولية"
|
||||
"postgres.version": "PostgreSQL Version",
|
||||
"postgres.raw-info": "Postgres Raw Info"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"errors": "Errors",
|
||||
"figure-x": "شكل %1",
|
||||
"error-events-per-day": "<code>%1</code> حدث كل يوم ",
|
||||
"error.404": "404 لم يتم العثور",
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
"events": "أحداث",
|
||||
"no-events": "لا توجد أحداث",
|
||||
"control-panel": "لوحة تحكم الأحداث",
|
||||
"delete-events": "حذف الاحداث",
|
||||
"confirm-delete-all-events": "هل أنت متاكد أنك تريد حذف كل سجل اﻻحداث؟",
|
||||
"filters": "تصفية",
|
||||
"filters-apply": "تطبيق التصفية",
|
||||
"filter-type": "نوع الحدث",
|
||||
"filter-start": "تاريخ البدء",
|
||||
"filter-end": "تاريخ الانتهاء",
|
||||
"filter-per-page": "لكل صفحة"
|
||||
"delete-events": "Delete Events",
|
||||
"filters": "Filters",
|
||||
"filters-apply": "Apply Filters",
|
||||
"filter-type": "Event Type",
|
||||
"filter-start": "Start Date",
|
||||
"filter-end": "End Date",
|
||||
"filter-perPage": "Per Page"
|
||||
}
|
||||
@@ -1,20 +1,16 @@
|
||||
{
|
||||
"customise": "Customise",
|
||||
"custom-css": "Custom CSS/SASS",
|
||||
"custom-css.description": "Enter your own CSS/SASS declarations here, which will be applied after all other styles.",
|
||||
"custom-css.enable": "Enable Custom CSS/SASS",
|
||||
"custom-css": "Custom CSS/LESS",
|
||||
"custom-css.description": "Enter your own CSS/LESS declarations here, which will be applied after all other styles.",
|
||||
"custom-css.enable": "Enable Custom CSS/LESS",
|
||||
|
||||
"custom-js": "Javascript مخصصة",
|
||||
"custom-js.description": "أدخل Javascript الخاص بك هنا. سيتم تنفيذها بعد تحميل الصفحة بالكامل.",
|
||||
"custom-js.enable": "تفعيل Javascript المخصصة",
|
||||
|
||||
"custom-header": "ترويسة مخصصة",
|
||||
"custom-header.description": "أدخل وسوم HTML المخصصة هنا (مثل: Meta Tags, وغيرها)، والتي سيتم تضمينها لجزئية <code><head></code> من ترميز المنتدى. يُسمح بعلامات البرمجة النصية، ولكن لا يُنصح بها ، نظرًا لأن علامة التبويب <a href=\"#custom-js\" data-toggle=\"tab\"> Custom Javascript </a> متاحة.",
|
||||
"custom-header.description": "Enter custom HTML here (ex. Meta Tags, etc.), which will be appended to the <code><head></code> section of your forum's markup. Script tags are allowed, but are discouraged, as the <a href=\"#custom-js\" data-toggle=\"tab\">Custom Javascript</a> tab is available.",
|
||||
"custom-header.enable": "تفعيل الترويسة المخصصة",
|
||||
|
||||
"custom-css.livereload": "تفعيل إعادة التحميل المباشرة",
|
||||
"custom-css.livereload.description": "فعل هذا الخيار لإجبار جميع الجلسات في الأجهزة التي قمت بتسجيل الدخول فيها بحسابك على التحديث عند النقر على زر الحفظ",
|
||||
"bsvariables": "_variables.scss",
|
||||
"bsvariables.description": "Override bootstrap variables here. You can also use a tool like <a href=\"https://bootstrap.build/app\">bootstrap.build</a> and paste the output here.<br/>Changes require a rebuild & restart.",
|
||||
"bsvariables.enable": "Enable _variables.scss"
|
||||
"custom-css.livereload.description": "فعل هذا الخيار لإجبار جميع الجلسات في الأجهزة التي قمت بتسجيل الدخول فيها بحسابك على التحديث عند النقر على زر الحفظ"
|
||||
}
|
||||
@@ -1,16 +1,7 @@
|
||||
{
|
||||
"skins": "Skins",
|
||||
"bootswatch-skins": "Bootswatch Skins",
|
||||
"custom-skins": "Custom Skins",
|
||||
"add-skin": "Add Skin",
|
||||
"save-custom-skins": "Save Custom Skins",
|
||||
"save-custom-skins-success": "Custom skins saved successfully",
|
||||
"custom-skin-name": "Custom Skin Name",
|
||||
"custom-skin-variables": "Custom Skin Variables",
|
||||
"loading": "جاري تحميل السمات...",
|
||||
"homepage": "الصفحة الرئيسية",
|
||||
"select-skin": "إختيار السمة",
|
||||
"revert-skin": "Revert Skin",
|
||||
"current-skin": "السمة الحالية",
|
||||
"skin-updated": "تم تحديث السمة",
|
||||
"applied-success": "تم تطبيق السمة %1 بنجاح",
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
{
|
||||
"themes": "Themes",
|
||||
"checking-for-installed": "جاري التحقق من القوالب المثبتة...",
|
||||
"homepage": "الصفحة الرئيسية",
|
||||
"select-theme": "إختيار القالب",
|
||||
"revert-theme": "Revert Theme",
|
||||
"current-theme": "القالب المستخدم حالياً",
|
||||
"no-themes": "لم يتم العثور على قوالب مثبتة",
|
||||
"revert-confirm": "هل أنت متأكد من أنك ترغب في استعادة قااب NodeBB الافتراضي؟",
|
||||
"theme-changed": "تم تغيير القالب",
|
||||
"revert-success": "لقد قمت بنجاح بإستعادة القالب الأساسي لـNodeBB",
|
||||
"restart-to-activate": "يرجى إعادة بناء وإعادة تشغيل NodeBB لتنشيط هذا الثيم."
|
||||
"restart-to-activate": "Please rebuild and restart your NodeBB to fully activate this theme."
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
{
|
||||
"forum-traffic": "حركة المنتدى",
|
||||
"forum-traffic": "Forum Traffic",
|
||||
"page-views": "مشاهدات الصفحات",
|
||||
"unique-visitors": "زائرين فريدين",
|
||||
"logins": "عمليات تسجيل الدخول",
|
||||
"new-users": "مستخدم جديد",
|
||||
"new-users": "New Users",
|
||||
"posts": "مشاركات",
|
||||
"topics": "مواضيع",
|
||||
"page-views-seven": "آخر 7 ايام",
|
||||
@@ -15,24 +14,23 @@
|
||||
"page-views-custom-help": "أدخل نطاقا زمنيا لمرات مشاهدة الصفحات التي ترغب في عرضها. إذا لم يظهر منتقي التاريخ، فإن التنسيق المقبول هو <code>YYYY-MM-DD</code>",
|
||||
"page-views-custom-error": "الرجاء إدخال نطاق تاريخ صالح بالتنسيق <code>YYYY-MM-DD</code>",
|
||||
|
||||
"stats.yesterday": "الأمس",
|
||||
"stats.today": "اليوم",
|
||||
"stats.last-week": "الاسبوع الماضي",
|
||||
"stats.this-week": "هذا الاسبوع",
|
||||
"stats.last-month": "الشهر الماضي",
|
||||
"stats.this-month": "هذا الشهر",
|
||||
"stats.yesterday": "Yesterday",
|
||||
"stats.today": "Today",
|
||||
"stats.last-week": "Last Week",
|
||||
"stats.this-week": "This Week",
|
||||
"stats.last-month": "Last Month",
|
||||
"stats.this-month": "This Month",
|
||||
"stats.all": "كل الوقت",
|
||||
|
||||
"updates": "تحديثات",
|
||||
"running-version": "المنتدى يعمل حاليا على <strong>NodeBB الإصدار<span id=\"version\">%1</span></strong>.",
|
||||
"keep-updated": "تأكد دائما من أن NodeBB يعمل على احدث إصدار للحصول على أحدث التصحيحات الأمنية وإصلاحات الأخطاء.",
|
||||
"up-to-date": "You are <strong>up-to-date</strong> <i class=\"fa fa-check\"></i>",
|
||||
"upgrade-available": "A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.",
|
||||
"prerelease-upgrade-available": "This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.",
|
||||
"prerelease-warning": "This is a <strong>pre-release</strong> version of NodeBB. Unintended bugs may occur. <i class=\"fa fa-exclamation-triangle\"></i>",
|
||||
"fallback-emailer-not-found": "مرسل البريد الإلكتروني الاحتياطي غير موجود!",
|
||||
"running-in-development": "Forum is running in development mode. The forum may be open to potential vulnerabilities; please contact your system administrator",
|
||||
"latest-lookup-failed": "Failed to look up latest available version of NodeBB",
|
||||
"up-to-date": "<p>المنتدى <strong>يعمل على أحدث إصدار</strong> <i class=\"fa fa-check\"></i></p>",
|
||||
"upgrade-available": "<p>A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
||||
"prerelease-upgrade-available": "<p>This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
||||
"prerelease-warning": "<p>هذه نسخة <strong>ماقبل الإصدار</strong> من NodeBB. قد تحدث أخطاء غير مقصودة. <i class=\"fa fa-exclamation-triangle\"></i></p>",
|
||||
"running-in-development": "المنتدى قيد التشغيل في وضع \"المطورين\". وقد تكون هناك ثغرات أمنية مفتوحة؛ من فضلك تواصل مع مسؤول نظامك.",
|
||||
"latest-lookup-failed": "<p>Failed to look up latest available version of NodeBB</p>",
|
||||
|
||||
"notices": "إشعارات",
|
||||
"restart-not-required": "إعادة التشغيل غير مطلوب",
|
||||
@@ -42,23 +40,22 @@
|
||||
"search-plugin-tooltip": "نصب إضافة البحث من صفحة الإضافات البرمجية لتنشيط وظيفة البحث",
|
||||
|
||||
"control-panel": "التحكم بالنظام",
|
||||
"rebuild-and-restart": "أعد البناء & وأعد التشغيل",
|
||||
"restart": "أعد التشغيل",
|
||||
"restart-warning": "ستؤدي إعادة بناء أو إعادة تشغيل NodeBB إلى إنقطاع الاتصال بالمنتدى لبضع ثوان.",
|
||||
"restart-disabled": "تم تعطيل إعادة بناء NodeBB وإعادة تشغيله حيث لا يبدو أنك تقوم بتشغيله عبر البرنامج الخفي المناسب.",
|
||||
"rebuild-and-restart": "Rebuild & Restart",
|
||||
"restart": "Restart",
|
||||
"restart-warning": "Rebuilding or Restarting your NodeBB will drop all existing connections for a few seconds.",
|
||||
"restart-disabled": "Rebuilding and Restarting your NodeBB has been disabled as you do not seem to be running it via the appropriate daemon.",
|
||||
"maintenance-mode": "وضع الصيانة",
|
||||
"maintenance-mode-title": "انقر هنا لإعداد وضع الصيانة لـNodeBB",
|
||||
"dark-mode": "Dark Mode",
|
||||
"realtime-chart-updates": "التحديث الفوري للرسم البياني",
|
||||
|
||||
"active-users": "المستخدمين النشطين",
|
||||
"active-users.users": "الأعضاء",
|
||||
"active-users.guests": "الزوار",
|
||||
"active-users.total": "المجموع",
|
||||
"active-users.connections": "روابط الاتصال",
|
||||
"active-users.connections": "Connections",
|
||||
|
||||
"guest-registered-users": "الزائر مقابل المستخدمين المسجلين",
|
||||
"guest": "الزائر",
|
||||
"anonymous-registered-users": "المجهولين مقابل المستخدمين المسجلين",
|
||||
"anonymous": "مجهول",
|
||||
"registered": "مسجل",
|
||||
|
||||
"user-presence": "تواجد المستخدمين",
|
||||
@@ -69,30 +66,14 @@
|
||||
"unread": "غير مقروء",
|
||||
|
||||
"high-presence-topics": "مواضيع ذات حضور قوي",
|
||||
"popular-searches": "عمليات البحث الشائعة",
|
||||
|
||||
"graphs.page-views": "مشاهدات الصفحة",
|
||||
"graphs.page-views-registered": "زيارات الصفحات المسجلة",
|
||||
"graphs.page-views-guest": "زيارات الصفحات للزوار",
|
||||
"graphs.page-views-bot": "زيارات الصفحات الآلية",
|
||||
"graphs.page-views-registered": "Page Views Registered",
|
||||
"graphs.page-views-guest": "Page Views Guest",
|
||||
"graphs.page-views-bot": "Page Views Bot",
|
||||
"graphs.unique-visitors": "زوار فريدين",
|
||||
"graphs.registered-users": "مستخدمين مسجلين",
|
||||
"graphs.guest-users": "المستخدمين الزوار",
|
||||
"last-restarted-by": "آخر إعادة تشغيل بواسطة",
|
||||
"no-users-browsing": "لا يوجد مستخدمين يتصفحون",
|
||||
|
||||
"back-to-dashboard": "العودة للوحة التحكم",
|
||||
"details.no-users": "لم ينضم أي مستخدم خلال الإطار الزمني المحدد",
|
||||
"details.no-topics": "لم يتم نشر أي مواضيع خلال الإطار الزمني المحدد",
|
||||
"details.no-searches": "لم يتم إجراء أي بحث خلال الإطار الزمني المحدد",
|
||||
"details.no-logins": "لم يوثق أي تسجيل دخول خلال الإطار الزمني المحدد",
|
||||
"details.logins-static": "يقوم NodeBB بحفظ بيانات الجلسة لمدة ٪1 يوم/أيام فقط، ولذا فإن هذا الجدول أدناه سيعرض فقط أحدث الجلسات النشطة",
|
||||
"details.logins-login-time": "وقت تسجيل الدخول",
|
||||
"start": "بدء",
|
||||
"end": "إنهاء",
|
||||
"filter": "تصفية",
|
||||
"view-as-json": "View as JSON",
|
||||
"expand-analytics": "Expand analytics",
|
||||
"clear-search-history": "Clear Search History",
|
||||
"clear-search-history-confirm": "Are you sure you want to clear entire search history?"
|
||||
"graphs.anonymous-users": "مستخدمين مجهولين",
|
||||
"last-restarted-by": "Last restarted by",
|
||||
"no-users-browsing": "No users browsing"
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
{
|
||||
"you-are-on": "أنت في <strong> %1:%2 </strong>",
|
||||
"ip": "رقم الآي بي <strong> %1 </strong>",
|
||||
"nodes-responded": "عدد %1 نقطة/نقاط استجابوا خلال %2 جزء من الثانية.",
|
||||
"host": "المضيف",
|
||||
"you-are-on": "You are on <strong>%1:%2</strong>",
|
||||
"ip": "IP <strong>%1</strong>",
|
||||
"nodes-responded": "%1 nodes responded within %2ms!",
|
||||
"host": "host",
|
||||
"primary": "primary / run jobs",
|
||||
"pid": "pid",
|
||||
"nodejs": "nodejs",
|
||||
"online": "online",
|
||||
"git": "git",
|
||||
"process-memory": "process memory",
|
||||
"system-memory": "system memory",
|
||||
"used-memory-process": "Used memory by process",
|
||||
"used-memory-os": "Used system memory",
|
||||
"total-memory-os": "Total system memory",
|
||||
"memory": "memory",
|
||||
"load": "system load",
|
||||
"cpu-usage": "cpu usage",
|
||||
"uptime": "uptime",
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"logger": "Logger",
|
||||
"logger-settings": "إعدادات المسجِّل",
|
||||
"description": "من خلال تمكين مربعات الاختيار ، ستتلقى سجلات إلى جهازك الطرفي. إذا حددت مسارًا ، فسيتم بعد ذلك حفظ السجلات في ملف بدلاً من ذلك. يعد تسجيل HTTP مفيدًا لجمع الإحصائيات حول من ومتى وماذا يصل الأشخاص في المنتدى. بالإضافة إلى تسجيل طلبات HTTP ، يمكننا أيضًا تسجيل أحداث socket.io. يمكن أن يكون تسجيل Socket.io ، جنبًا إلى جنب مع شاشة redis-cli ، مفيدًا جدًا في تعلم العناصر الداخلية لـ NodeBB.",
|
||||
"explanation": "ما عليك سوى تحديدأو/ إلغاء تحديد إعدادات التسجيل لتمكين أو تعطيل التسجيل أثناء التنقل. لا حاجة لإعادة التشغيل.",
|
||||
"enable-http": "تمكين سجلات HTTP",
|
||||
"enable-socket": "تفعيل تسجيل أحداث socket.io",
|
||||
"file-path": "مسار ملف السجل",
|
||||
"file-path-placeholder": "/path/to/log/file.log ::: اتركه فارغا لاظهار السجلات لنافذة الطرفية",
|
||||
"logger-settings": "Logger Settings",
|
||||
"description": "By enabling the check boxes, you will receive logs to your terminal. If you specify a path, logs will then be saved to a file instead. HTTP logging is useful for collecting statistics about who, when, and what people access on your forum. In addition to logging HTTP requests, we can also log socket.io events. Socket.io logging, in combination with redis-cli monitor, can be very helpful for learning NodeBB's internals.",
|
||||
"explanation": "Simply check/uncheck the logging settings to enable or disable logging on the fly. No restart needed.",
|
||||
"enable-http": "Enable HTTP logging",
|
||||
"enable-socket": "Enable socket.io event logging",
|
||||
"file-path": "Path to log file",
|
||||
"file-path-placeholder": "/path/to/log/file.log ::: leave blank to log to your terminal",
|
||||
|
||||
"control-panel": "لوحة تحكم المسجل",
|
||||
"update-settings": "تحديث إعدادات المسجل"
|
||||
"control-panel": "Logger Control Panel",
|
||||
"update-settings": "Update Logger Settings"
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"plugins": "Plugins",
|
||||
"trending": "Trending",
|
||||
"installed": "منصبة",
|
||||
"active": "مفعلة",
|
||||
@@ -40,7 +39,7 @@
|
||||
"alert.upgraded": "الإضافة مرقاة",
|
||||
"alert.installed": "الإضافة منصبة",
|
||||
"alert.uninstalled": "تم إلغاء تنصيب الإضافة",
|
||||
"alert.activate-success": "Please rebuild and restart your NodeBB to fully activate this plugin",
|
||||
"alert.activate-success": "يرجى إعادة تشغيل NodeBB لتنشيط الإضافة بشكل بالكامل",
|
||||
"alert.deactivate-success": "تم تعطيل الإضافة بنجاح",
|
||||
"alert.upgrade-success": "Please rebuild and restart your NodeBB to fully upgrade this plugin.",
|
||||
"alert.install-success": "تم تثبيت الإضافة بنجاح، يرجى تفعيلها.",
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"rewards": "المكافآت",
|
||||
"add-reward": "Add reward",
|
||||
"condition-if-users": "إذا كان للمستخدم",
|
||||
"condition-is": "يكون: ",
|
||||
"condition-then": "عندئذ:",
|
||||
"max-claims": "عدد المرات التي يمكن فيها المطالبة بالمكافأة",
|
||||
"zero-infinite": "أدخل 0 للقيمة اللانهائية",
|
||||
"select-reward": "Select reward",
|
||||
"delete": "احذف",
|
||||
"enable": "مكّن",
|
||||
"disable": "عطّل",
|
||||
"rewards": "Rewards",
|
||||
"condition-if-users": "If User's",
|
||||
"condition-is": "Is:",
|
||||
"condition-then": "Then:",
|
||||
"max-claims": "Amount of times reward is claimable",
|
||||
"zero-infinite": "Enter 0 for infinite",
|
||||
"delete": "Delete",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"control-panel": "Rewards Control",
|
||||
"new-reward": "New Reward",
|
||||
|
||||
"alert.delete-success": "المكافآت المحذوفة بنجاح",
|
||||
"alert.no-inputs-found": "مكافأة غير قانونية - لم يتم العثور على مدخلات!",
|
||||
"alert.save-success": "المكافآت المحفوظة بنجاح"
|
||||
"alert.delete-success": "Successfully deleted reward",
|
||||
"alert.no-inputs-found": "Illegal reward - no inputs found!",
|
||||
"alert.save-success": "Successfully saved rewards"
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
{
|
||||
"widgets": "Widgets",
|
||||
"available": "Available Widgets",
|
||||
"explanation": "Select a widget from the dropdown menu and then drag and drop it into a template's widget area on the left.",
|
||||
"none-installed": "No widgets found! Activate the widget essentials plugin in the <a href=\"%1\">plugins</a> control panel.",
|
||||
"clone-from": "Clone widgets from",
|
||||
"containers.available": "Available Containers",
|
||||
"containers.explanation": "Drag and drop on top of any widget",
|
||||
"containers.explanation": "Drag and drop on top of any active widget",
|
||||
"containers.none": "None",
|
||||
"container.well": "Well",
|
||||
"container.jumbotron": "Jumbotron",
|
||||
"container.card": "Card",
|
||||
"container.card-header": "Card Header",
|
||||
"container.card-body": "Card Body",
|
||||
"container.panel": "Panel",
|
||||
"container.panel-header": "Panel Header",
|
||||
"container.panel-body": "Panel Body",
|
||||
"container.alert": "Alert",
|
||||
|
||||
"alert.confirm-delete": "Are you sure you wish to delete this widget?",
|
||||
@@ -27,9 +26,5 @@
|
||||
"container.placeholder": "Drag and drop a container or enter HTML here.",
|
||||
"show-to-groups": "Show to groups",
|
||||
"hide-from-groups": "Hide from groups",
|
||||
"start-date": "Start date",
|
||||
"end-date": "End date",
|
||||
"hide-on-mobile": "Hide on mobile",
|
||||
"hide-drafts": "Hide drafts",
|
||||
"show-drafts": "Show drafts"
|
||||
"hide-on-mobile": "Hide on mobile"
|
||||
}
|
||||
79
public/language/ar/admin/general/dashboard.json
Normal file
79
public/language/ar/admin/general/dashboard.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"forum-traffic": "Forum Traffic",
|
||||
"page-views": "مشاهدات الصفحات",
|
||||
"unique-visitors": "زائرين فريدين",
|
||||
"new-users": "New Users",
|
||||
"posts": "مشاركات",
|
||||
"topics": "مواضيع",
|
||||
"page-views-seven": "آخر 7 ايام",
|
||||
"page-views-thirty": "آخر 30 يوماً",
|
||||
"page-views-last-day": "آخر 24 ساعة",
|
||||
"page-views-custom": "مدة زمنية مخصصة",
|
||||
"page-views-custom-start": "بداية المدة",
|
||||
"page-views-custom-end": "نهاية المده",
|
||||
"page-views-custom-help": "أدخل نطاقا زمنيا لمرات مشاهدة الصفحات التي ترغب في عرضها. إذا لم يظهر منتقي التاريخ، فإن التنسيق المقبول هو <code>YYYY-MM-DD</code>",
|
||||
"page-views-custom-error": "الرجاء إدخال نطاق تاريخ صالح بالتنسيق <code>YYYY-MM-DD</code>",
|
||||
|
||||
"stats.yesterday": "Yesterday",
|
||||
"stats.today": "Today",
|
||||
"stats.last-week": "Last Week",
|
||||
"stats.this-week": "This Week",
|
||||
"stats.last-month": "Last Month",
|
||||
"stats.this-month": "This Month",
|
||||
"stats.all": "كل الوقت",
|
||||
|
||||
"updates": "تحديثات",
|
||||
"running-version": "المنتدى يعمل حاليا على <strong>NodeBB الإصدار<span id=\"version\">%1</span></strong>.",
|
||||
"keep-updated": "تأكد دائما من أن NodeBB يعمل على احدث إصدار للحصول على أحدث التصحيحات الأمنية وإصلاحات الأخطاء.",
|
||||
"up-to-date": "<p>المنتدى <strong>يعمل على أحدث إصدار</strong> <i class=\"fa fa-check\"></i></p>",
|
||||
"upgrade-available": "<p>A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
||||
"prerelease-upgrade-available": "<p>This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
||||
"prerelease-warning": "<p>هذه نسخة <strong>ماقبل الإصدار</strong> من NodeBB. قد تحدث أخطاء غير مقصودة. <i class=\"fa fa-exclamation-triangle\"></i></p>",
|
||||
"running-in-development": "المنتدى قيد التشغيل في وضع \"المطورين\". وقد تكون هناك ثغرات أمنية مفتوحة؛ من فضلك تواصل مع مسؤول نظامك.",
|
||||
"latest-lookup-failed": "<p>Failed to look up latest available version of NodeBB</p>",
|
||||
|
||||
"notices": "إشعارات",
|
||||
"restart-not-required": "إعادة التشغيل غير مطلوب",
|
||||
"restart-required": "إعادة التشغيل مطلوبة",
|
||||
"search-plugin-installed": "إضافة البحث منصبة",
|
||||
"search-plugin-not-installed": "إضافة البحث غير منصبة",
|
||||
"search-plugin-tooltip": "نصب إضافة البحث من صفحة الإضافات البرمجية لتنشيط وظيفة البحث",
|
||||
|
||||
"control-panel": "التحكم بالنظام",
|
||||
"rebuild-and-restart": "Rebuild & Restart",
|
||||
"restart": "Restart",
|
||||
"restart-warning": "Rebuilding or Restarting your NodeBB will drop all existing connections for a few seconds.",
|
||||
"restart-disabled": "Rebuilding and Restarting your NodeBB has been disabled as you do not seem to be running it via the appropriate daemon.",
|
||||
"maintenance-mode": "وضع الصيانة",
|
||||
"maintenance-mode-title": "انقر هنا لإعداد وضع الصيانة لـNodeBB",
|
||||
"realtime-chart-updates": "التحديث الفوري للرسم البياني",
|
||||
|
||||
"active-users": "المستخدمين النشطين",
|
||||
"active-users.users": "الأعضاء",
|
||||
"active-users.guests": "الزوار",
|
||||
"active-users.total": "المجموع",
|
||||
"active-users.connections": "Connections",
|
||||
|
||||
"anonymous-registered-users": "المجهولين مقابل المستخدمين المسجلين",
|
||||
"anonymous": "مجهول",
|
||||
"registered": "مسجل",
|
||||
|
||||
"user-presence": "تواجد المستخدمين",
|
||||
"on-categories": "في قائمة الأقسام",
|
||||
"reading-posts": "قراءة المشاركات",
|
||||
"browsing-topics": "تصفح المواضيع",
|
||||
"recent": "الأخيرة",
|
||||
"unread": "غير مقروء",
|
||||
|
||||
"high-presence-topics": "مواضيع ذات حضور قوي",
|
||||
|
||||
"graphs.page-views": "مشاهدات الصفحة",
|
||||
"graphs.page-views-registered": "Page Views Registered",
|
||||
"graphs.page-views-guest": "Page Views Guest",
|
||||
"graphs.page-views-bot": "Page Views Bot",
|
||||
"graphs.unique-visitors": "زوار فريدين",
|
||||
"graphs.registered-users": "مستخدمين مسجلين",
|
||||
"graphs.anonymous-users": "مستخدمين مجهولين",
|
||||
"last-restarted-by": "Last restarted by",
|
||||
"no-users-browsing": "No users browsing"
|
||||
}
|
||||
6
public/language/ar/admin/general/languages.json
Normal file
6
public/language/ar/admin/general/languages.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"language-settings": "اعدادات اللغة",
|
||||
"description": "تُحدد اللغة الافتراضية إعدادات اللغة لجميع المستخدمين الذين يزورون المنتدى. <br />يمكن للأعضاء تجاوز اللغة الافتراضية من خلال صفحة إعدادات الحساب الخاصة بهم.",
|
||||
"default-language": "اللغة الافتراضية",
|
||||
"auto-detect": "الكشف عن إعدادات اللغة للزوار بشكل آلي"
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"navigation": "Navigation",
|
||||
"icon": "Icon:",
|
||||
"change-icon": "change",
|
||||
"route": "Route:",
|
||||
@@ -12,8 +11,6 @@
|
||||
"properties": "Properties:",
|
||||
"groups": "Groups:",
|
||||
"open-new-window": "Open in a new window",
|
||||
"dropdown": "Dropdown",
|
||||
"dropdown-placeholder": "Place your dropdown menu items below, ie: <br/><li><a class="dropdown-item" href="https://myforum.com">Link 1</a></li>",
|
||||
|
||||
"btn.delete": "Delete",
|
||||
"btn.disable": "Disable",
|
||||
@@ -23,4 +20,4 @@
|
||||
"custom-route": "Custom Route",
|
||||
"core": "core",
|
||||
"plugin": "plugin"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"post-sharing": "Post Sharing",
|
||||
"info-plugins-additional": "Plugins can add additional networks for sharing posts."
|
||||
"info-plugins-additional": "Plugins can add additional networks for sharing posts.",
|
||||
"save-success": "Successfully saved Post Sharing Networks!"
|
||||
}
|
||||
9
public/language/ar/admin/general/sounds.json
Normal file
9
public/language/ar/admin/general/sounds.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"notifications": "التنبيهات",
|
||||
"chat-messages": "Chat Messages",
|
||||
"play-sound": "Play",
|
||||
"incoming-message": "Incoming Message",
|
||||
"outgoing-message": "Outgoing Message",
|
||||
"upload-new-sound": "Upload New Sound",
|
||||
"saved": "Settings Saved"
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
{
|
||||
"manage-admins-and-mods": "Manage Admins & Mods",
|
||||
"administrators": "Administrators",
|
||||
"global-moderators": "Global Moderators",
|
||||
"moderators": "Moderators",
|
||||
"no-global-moderators": "No Global Moderators",
|
||||
"no-sub-categories": "No subcategories",
|
||||
"view-children": "View children (%1)",
|
||||
"moderators-of-category": "%1 Moderators",
|
||||
"no-moderators": "No Moderators",
|
||||
"add-administrator": "Add Administrator",
|
||||
"add-global-moderator": "Add Global Moderator",
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
{
|
||||
"manage-categories": "Manage Categories",
|
||||
"add-category": "Add category",
|
||||
"jump-to": "Jump to...",
|
||||
"settings": "اعدادات القسم",
|
||||
"edit-category": "Edit Category",
|
||||
"privileges": "الصلاحيات",
|
||||
"back-to-categories": "Back to categories",
|
||||
|
||||
"name": "Category Name",
|
||||
"description": "Category Description",
|
||||
"bg-color": "Background Colour",
|
||||
@@ -14,18 +10,13 @@
|
||||
"custom-class": "Custom Class",
|
||||
"num-recent-replies": "# of Recent Replies",
|
||||
"ext-link": "External Link",
|
||||
"subcategories-per-page": "Subcategories per page",
|
||||
"is-section": "Treat this category as a section",
|
||||
"post-queue": "Post queue",
|
||||
"tag-whitelist": "Tag Whitelist",
|
||||
"upload-image": "Upload Image",
|
||||
"upload": "Upload",
|
||||
"delete-image": "Remove",
|
||||
"category-image": "Category Image",
|
||||
"image-and-icon": "Image & Icon",
|
||||
"parent-category": "Parent Category",
|
||||
"optional-parent-category": "(Optional) Parent Category",
|
||||
"top-level": "Top Level",
|
||||
"parent-category-none": "(None)",
|
||||
"copy-parent": "Copy Parent",
|
||||
"copy-settings": "Copy Settings From",
|
||||
@@ -37,10 +28,7 @@
|
||||
"disable": "Disable",
|
||||
"edit": "Edit",
|
||||
"analytics": "Analytics",
|
||||
|
||||
"view-category": "View category",
|
||||
"set-order": "Set order",
|
||||
"set-order-help": "Setting the order of the category will move this category to that order and update the order of other categories as necessary. Minimum order is 1 which puts the category at the top.",
|
||||
|
||||
"select-category": "Select Category",
|
||||
"set-parent-category": "Set Parent Category",
|
||||
@@ -57,8 +45,6 @@
|
||||
"privileges.no-users": "No user-specific privileges in this category.",
|
||||
"privileges.section-group": "Group",
|
||||
"privileges.group-private": "This group is private",
|
||||
"privileges.inheritance-exception": "This group does not inherit privileges from registered-users group",
|
||||
"privileges.banned-user-inheritance": "Banned users inherit privileges from banned-users group",
|
||||
"privileges.search-group": "Add Group",
|
||||
"privileges.copy-to-children": "Copy to Children",
|
||||
"privileges.copy-from-category": "Copy from Category",
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"resent-single": "Manual digest resend completed",
|
||||
"resent-day": "Daily digest resent",
|
||||
"resent-week": "Weekly digest resent",
|
||||
"resent-biweek": "Bi-Weekly digest resent",
|
||||
"resent-month": "Monthly digest resent",
|
||||
"null": "<em>Never</em>",
|
||||
"manual-run": "Manual digest run:",
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
{
|
||||
"manage-groups": "Manage Groups",
|
||||
"add-group": "Add group",
|
||||
"edit-group": "Edit Group",
|
||||
"back-to-groups": "Back to groups",
|
||||
"view-group": "View group",
|
||||
"icon-and-title": "Icon & Title",
|
||||
"name": "اسم المجموعة",
|
||||
"badge": "Badge",
|
||||
"properties": "Properties",
|
||||
@@ -16,7 +10,7 @@
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"privileges": "Privileges",
|
||||
"members-csv": "Members (CSV)",
|
||||
"download-csv": "CSV",
|
||||
"search-placeholder": "Search",
|
||||
"create": "Create Group",
|
||||
"description-placeholder": "A short description about your group",
|
||||
@@ -45,5 +39,6 @@
|
||||
"revert": "Revert",
|
||||
|
||||
"edit.no-users-found": "No Users Found",
|
||||
"edit.confirm-remove-user": "Are you sure you want to remove this user?"
|
||||
"edit.confirm-remove-user": "Are you sure you want to remove this user?",
|
||||
"edit.save-success": "Changes saved!"
|
||||
}
|
||||
@@ -1,19 +1,14 @@
|
||||
{
|
||||
"manage-privileges": "Manage Privileges",
|
||||
"discard-changes": "Discard changes",
|
||||
"global": "Global",
|
||||
"admin": "Admin",
|
||||
"group-privileges": "Group Privileges",
|
||||
"user-privileges": "User Privileges",
|
||||
"edit-privileges": "Edit Privileges",
|
||||
"select-clear-all": "Select/Clear All",
|
||||
"chat": "Chat",
|
||||
"chat-with-privileged": "Chat with Privileged",
|
||||
"upload-images": "Upload Images",
|
||||
"upload-files": "Upload Files",
|
||||
"signature": "Signature",
|
||||
"ban": "Ban",
|
||||
"mute": "Mute",
|
||||
"invite": "Invite",
|
||||
"search-content": "Search Content",
|
||||
"search-users": "Search Users",
|
||||
@@ -29,12 +24,11 @@
|
||||
"access-topics": "Access Topics",
|
||||
"create-topics": "Create Topics",
|
||||
"reply-to-topics": "Reply to Topics",
|
||||
"schedule-topics": "Schedule Topics",
|
||||
"tag-topics": "Tag Topics",
|
||||
"edit-posts": "Edit Posts",
|
||||
"view-edit-history": "View Edit History",
|
||||
"delete-posts": "Delete Posts",
|
||||
"view-deleted": "View Deleted Posts",
|
||||
"view_deleted": "View Deleted Posts",
|
||||
"upvote-posts": "Upvote Posts",
|
||||
"downvote-posts": "Downvote Posts",
|
||||
"delete-topics": "Delete Topics",
|
||||
@@ -44,23 +38,17 @@
|
||||
"admin-categories": "Categories",
|
||||
"admin-privileges": "Privileges",
|
||||
"admin-users": "Users",
|
||||
"admin-admins-mods": "Admins & Mods",
|
||||
"admin-groups": "Groups",
|
||||
"admin-tags": "Tags",
|
||||
"admin-settings": "Settings",
|
||||
|
||||
"alert.confirm-moderate": "<strong>Are you sure you wish to grant the moderation privilege to this user group?</strong> This group is public, and any users can join at will.",
|
||||
"alert.confirm-admins-mods": "<strong>Are you sure you wish to grant the "Admins & Mods" privilege to this user/group?</strong> Users with this privilege are able to promote and demote other users into privileged positions, <em>including super administrator</em>",
|
||||
"alert.confirm-save": "Please confirm your intention to save these privileges",
|
||||
"alert.saved": "Privilege changes saved and applied",
|
||||
"alert.confirm-discard": "Are you sure you wish to discard your privilege changes?",
|
||||
"alert.discarded": "Privilege changes discarded",
|
||||
"alert.confirm-copyToAll": "Are you sure you wish to apply this set of <strong>%1</strong> to <strong>all categories</strong>?",
|
||||
"alert.confirm-copyToAllGroup": "Are you sure you wish to apply this group's set of <strong>%1</strong> to <strong>all categories</strong>?",
|
||||
"alert.confirm-copyToChildren": "Are you sure you wish to apply this set of <strong>%1</strong> to <strong>all descendant (child) categories</strong>?",
|
||||
"alert.confirm-copyToChildrenGroup": "Are you sure you wish to apply this group's set of <strong>%1</strong> to <strong>all descendant (child) categories</strong>?",
|
||||
"alert.confirm-copyToAll": "Are you sure you wish to apply this privilege set to <strong>all categories</strong>?",
|
||||
"alert.confirm-copyToAllGroup": "Are you sure you wish to apply this group's privilege set to <strong>all categories</strong>?",
|
||||
"alert.confirm-copyToChildren": "Are you sure you wish to apply this privilege set to <strong>all descendant (child) categories</strong>?",
|
||||
"alert.confirm-copyToChildrenGroup": "Are you sure you wish to apply this group's privilege set to <strong>all descendant (child) categories</strong>?",
|
||||
"alert.no-undo": "<em>This action cannot be undone.</em>",
|
||||
"alert.admin-warning": "Administrators implicitly get all privileges",
|
||||
"alert.copyPrivilegesFrom-title": "Select a category to copy from",
|
||||
"alert.copyPrivilegesFrom-warning": "This will copy <strong>%1</strong> from the selected category.",
|
||||
"alert.copyPrivilegesFromGroup-warning": "This will copy this group's set of <strong>%1</strong> from the selected category."
|
||||
"alert.admin-warning": "Administrators implicitly get all privileges"
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"queue": "الطابور",
|
||||
"queue": "Queue",
|
||||
"description": "There are no users in the registration queue. <br> To enable this feature, go to <a href=\"%1\">Settings → User → User Registration</a> and set <strong>Registration Type</strong> to \"Admin Approval\".",
|
||||
|
||||
"list.name": "اﻹسم",
|
||||
"list.email": "البريد الإلكتروني",
|
||||
"list.name": "Name",
|
||||
"list.email": "Email",
|
||||
"list.ip": "IP",
|
||||
"list.time": "التوقيت",
|
||||
"list.time": "Time",
|
||||
"list.username-spam": "Frequency: %1 Appears: %2 Confidence: %3",
|
||||
"list.email-spam": "Frequency: %1 Appears: %2",
|
||||
"list.ip-spam": "Frequency: %1 Appears: %2",
|
||||
|
||||
"invitations": "الدعوات",
|
||||
"invitations": "Invitations",
|
||||
"invitations.description": "Below is a complete list of invitations sent. Use ctrl-f to search through the list by email or username. <br><br>The username will be displayed to the right of the emails for users who have redeemed their invitations.",
|
||||
"invitations.inviter-username": "أسم المستخدم الداعي",
|
||||
"invitations.invitee-email": "البريد اﻻلكتروني للمدعو",
|
||||
"invitations.invitee-username": "اسم المستخم للمدعو (اذا كان مسجل)",
|
||||
"invitations.inviter-username": "Inviter Username",
|
||||
"invitations.invitee-email": "Invitee Email",
|
||||
"invitations.invitee-username": "Invitee Username (if registered)",
|
||||
|
||||
"invitations.confirm-delete": "هل أنت متأكد من أنك تريد حذف هذه الدعوة؟"
|
||||
"invitations.confirm-delete": "Are you sure you wish to delete this invitation?"
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"manage-tags": "Manage Tags",
|
||||
"none": "Your forum does not have any topics with tags yet.",
|
||||
"bg-color": "Background Colour",
|
||||
"text-color": "Text Colour",
|
||||
"create-modify": "Create & Modify Tags",
|
||||
"description": "Select tags by clicking or dragging, use <code>CTRL</code> to select multiple tags.",
|
||||
"create": "Create Tag",
|
||||
"add-tag": "Add tag",
|
||||
"modify": "Modify Tags",
|
||||
"rename": "Rename Tags",
|
||||
"delete": "Delete Selected Tags",
|
||||
@@ -15,6 +14,5 @@
|
||||
|
||||
"alerts.editing": "Editing tag(s)",
|
||||
"alerts.confirm-delete": "Do you want to delete the selected tags?",
|
||||
"alerts.update-success": "Tag Updated!",
|
||||
"reset-colors": "Reset colors"
|
||||
"alerts.update-success": "Tag Updated!"
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
{
|
||||
"manage-uploads": "Manage Uploads",
|
||||
"upload-file": "Upload File",
|
||||
"filename": "Filename",
|
||||
"usage": "Post Usage",
|
||||
"orphaned": "Orphaned",
|
||||
"size/filecount": "Size / Filecount",
|
||||
"confirm-delete": "Do you really want to delete this file?",
|
||||
"filecount": "%1 files",
|
||||
"new-folder": "New Folder",
|
||||
"name-new-folder": "Enter a name for new the folder"
|
||||
"filecount": "%1 files"
|
||||
}
|
||||
@@ -1,32 +1,24 @@
|
||||
{
|
||||
"manage-users": "Manage Users",
|
||||
"users": "المستخدمين",
|
||||
"edit": "Actions",
|
||||
"edit": "تحرير",
|
||||
"make-admin": "Make Admin",
|
||||
"remove-admin": "Remove Admin",
|
||||
"change-email": "Change Email",
|
||||
"new-email": "New Email",
|
||||
"validate-email": "Validate Email",
|
||||
"send-validation-email": "Send Validation Email",
|
||||
"change-password": "Change Password",
|
||||
"password-reset-email": "Send Password Reset Email",
|
||||
"force-password-reset": "Force Password Reset & Log User Out",
|
||||
"ban": "Ban",
|
||||
"ban-users": "Ban User(s)",
|
||||
"ban": "Ban User(s)",
|
||||
"temp-ban": "Ban User(s) Temporarily",
|
||||
"unban": "Unban User(s)",
|
||||
"reset-lockout": "Reset Lockout",
|
||||
"reset-flags": "Reset Flags",
|
||||
"delete": "Delete",
|
||||
"delete-users": "Delete <strong>User(s)</strong>",
|
||||
"delete": "Delete <strong>User(s)</strong>",
|
||||
"delete-content": "Delete User(s) <strong>Content</strong>",
|
||||
"purge": "Delete <strong>User(s)</strong> and <strong>Content</strong>",
|
||||
"download-csv": "Download CSV",
|
||||
"manage-groups": "Manage Groups",
|
||||
"set-reputation": "Set Reputation",
|
||||
"add-group": "Add Group",
|
||||
"create": "Create User",
|
||||
"invite": "Invite by Email",
|
||||
"invite": "Invite",
|
||||
"new": "New User",
|
||||
"filter-by": "Filter by",
|
||||
"pills.unvalidated": "Not Validated",
|
||||
@@ -55,12 +47,6 @@
|
||||
"users.uid": "uid",
|
||||
"users.username": "username",
|
||||
"users.email": "email",
|
||||
"users.no-email": "(no email)",
|
||||
"users.validated": "Validated",
|
||||
"users.not-validated": "Not Validated",
|
||||
"users.validation-pending": "Validation Pending",
|
||||
"users.validation-expired": "Validation Expired",
|
||||
"users.ip": "IP",
|
||||
"users.postcount": "postcount",
|
||||
"users.reputation": "reputation",
|
||||
"users.flags": "flags",
|
||||
@@ -74,7 +60,7 @@
|
||||
"create.password": "Password",
|
||||
"create.password-confirm": "Confirm Password",
|
||||
|
||||
"temp-ban.length": "Length",
|
||||
"temp-ban.length": "Ban Length",
|
||||
"temp-ban.reason": "Reason <span class=\"text-muted\">(Optional)</span>",
|
||||
"temp-ban.hours": "Hours",
|
||||
"temp-ban.days": "Days",
|
||||
@@ -86,7 +72,6 @@
|
||||
"alerts.button-ban-x": "Ban %1 user(s)",
|
||||
"alerts.unban-success": "User(s) unbanned!",
|
||||
"alerts.lockout-reset-success": "Lockout(s) reset!",
|
||||
"alerts.password-change-success": "Password(s) changed!",
|
||||
"alerts.flag-reset-success": "Flags(s) reset!",
|
||||
"alerts.no-remove-yourself-admin": "You can't remove yourself as Administrator!",
|
||||
"alerts.make-admin-success": "User is now administrator.",
|
||||
@@ -103,7 +88,6 @@
|
||||
"alerts.validate-email-success": "Emails validated",
|
||||
"alerts.validate-force-password-reset-success": "User(s) passwords have been reset and their existing sessions have been revoked.",
|
||||
"alerts.password-reset-confirm": "Do you want to send password reset email(s) to these user(s)?",
|
||||
"alerts.password-reset-email-sent": "Password reset email sent.",
|
||||
"alerts.confirm-delete": "<strong>Warning!</strong><p>Do you really want to delete <strong>user(s)</strong>?</p><p>This action is not reversible! Only the user account will be deleted, their posts and topics will remain.</p>",
|
||||
"alerts.delete-success": "User(s) Deleted!",
|
||||
"alerts.confirm-delete-content": "<strong>Warning!</strong><p>Do you really want to delete these user(s) <strong>content</strong>?</p><p>This action is not reversible! The users' accounts will remain, but their posts and topics will be deleted.</p>",
|
||||
@@ -112,18 +96,11 @@
|
||||
"alerts.create": "Create User",
|
||||
"alerts.button-create": "Create",
|
||||
"alerts.button-cancel": "Cancel",
|
||||
"alerts.button-change": "Change",
|
||||
"alerts.error-passwords-different": "Passwords must match!",
|
||||
"alerts.error-x": "<strong>Error</strong><p>%1</p>",
|
||||
"alerts.create-success": "User created!",
|
||||
|
||||
"alerts.prompt-email": "Emails: ",
|
||||
"alerts.email-sent-to": "An invitation email has been sent to %1",
|
||||
"alerts.x-users-found": "%1 user(s) found, (%2 seconds)",
|
||||
"alerts.select-a-single-user-to-change-email": "Select a single user to change email",
|
||||
"export-users-started": "Exporting users as csv, this might take a while. You will receive a notification when it is complete.",
|
||||
"export-users-completed": "Users exported as csv, click here to download.",
|
||||
"email": "Email",
|
||||
"password": "Password",
|
||||
"manage": "Manage"
|
||||
"alerts.x-users-found": "%1 user(s) found, (%2 seconds)"
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
{
|
||||
"section-dashboard": "Dashboards",
|
||||
"dashboard/overview": "Overview",
|
||||
"dashboard/logins": "Logins",
|
||||
"dashboard/users": "Users",
|
||||
"dashboard/topics": "Topics",
|
||||
"dashboard/searches": "Searches",
|
||||
"dashboard": "Dashboard",
|
||||
"section-general": "عام",
|
||||
|
||||
"section-manage": "إدارة",
|
||||
@@ -14,7 +9,6 @@
|
||||
"manage/users": "الأعضاء",
|
||||
"manage/admins-mods": "Admins & Mods",
|
||||
"manage/registration": "قائمة انتظار التسجيل",
|
||||
"manage/flagged-content": "Flagged Content",
|
||||
"manage/post-queue": "قائمة انتظار المشاركة",
|
||||
"manage/groups": "المجموعات",
|
||||
"manage/ip-blacklist": "قائمة حظر عناوين IP",
|
||||
@@ -73,13 +67,11 @@
|
||||
"development/info": "Info",
|
||||
|
||||
"rebuild-and-restart-forum": "Rebuild & Restart Forum",
|
||||
"rebuild-and-restart": "Rebuild & Restart",
|
||||
"restart-forum": "Restart Forum",
|
||||
"restart": "Restart",
|
||||
"logout": "Log out",
|
||||
"view-forum": "View Forum",
|
||||
|
||||
"search.placeholder": "Search settings",
|
||||
"search.placeholder": "Press "/" to search for settings",
|
||||
"search.no-results": "No results...",
|
||||
"search.search-forum": "Search the forum for <strong></strong>",
|
||||
"search.keep-typing": "Type more to see results...",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"maintenance-mode.help": "When the forum is in maintenance mode, all requests will be redirected to a static holding page. Administrators are exempt from this redirection, and are able to access the site normally.",
|
||||
"maintenance-mode.status": "Maintenance Mode Status Code",
|
||||
"maintenance-mode.message": "Maintenance Message",
|
||||
"maintenance-mode.groups-exempt-from-maintenance-mode": "Select groups that should be exempt from maintenance mode",
|
||||
"headers": "Headers",
|
||||
"headers.allow-from": "Set ALLOW-FROM to Place NodeBB in an iFrame",
|
||||
"headers.csp-frame-ancestors": "Set Content-Security-Policy frame-ancestors header to Place NodeBB in an iFrame",
|
||||
@@ -16,12 +15,6 @@
|
||||
"headers.acac": "Access-Control-Allow-Credentials",
|
||||
"headers.acam": "Access-Control-Allow-Methods",
|
||||
"headers.acah": "Access-Control-Allow-Headers",
|
||||
"headers.coep": "Cross-Origin-Embedder-Policy",
|
||||
"headers.coep-help": "When enabled (default), will set the header to <code>require-corp</code>",
|
||||
"headers.coop": "Cross-Origin-Opener-Policy",
|
||||
"headers.corp": "Cross-Origin-Resource-Policy",
|
||||
"headers.permissions-policy": "Permissions-Policy",
|
||||
"headers.permissions-policy-help": "Allows setting permissions policy header, for example \"geolocation=*, camera=()\", see <a href=\"https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md\">this</a> for more info.",
|
||||
"hsts": "Strict Transport Security",
|
||||
"hsts.enabled": "Enabled HSTS (recommended)",
|
||||
"hsts.maxAge": "HSTS Max Age",
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
{
|
||||
"tokens": "Tokens",
|
||||
"settings": "Settings",
|
||||
"lead-text": "From this page you can configure access to the Write API in NodeBB.",
|
||||
"intro": "By default, the Write API authenticates users based on their session cookie, but NodeBB also supports Bearer authentication via tokens generated via this page.",
|
||||
"warning": "<strong>Be advised</strong> — treat tokens like passwords. If they are leaked, your account should be considered compromised.",
|
||||
"docs": "Click here to access the full API specification",
|
||||
|
||||
"require-https": "Require API usage via HTTPS only",
|
||||
"require-https-caveat": "<strong>Note</strong>: Some installations involving load balancers may proxy their requests to NodeBB using HTTP, in which case this option should remain disabled.",
|
||||
|
||||
"uid": "User ID",
|
||||
"token": "Token",
|
||||
"uid-help-text": "Specify a User ID to associate with this token. If the user ID is <code>0</code>, it will be considered a <em>master</em> token, which can assume the identity of other users based on the <code>_uid</code> parameter",
|
||||
"description": "Description",
|
||||
"last-seen": "Last seen",
|
||||
"created": "Created",
|
||||
"create-token": "Create Token",
|
||||
"update-token": "Update Token",
|
||||
"master-token": "Master token",
|
||||
"last-seen-never": "This key has never been used.",
|
||||
"no-description": "No description specified.",
|
||||
"actions": "Actions",
|
||||
"edit": "Edit",
|
||||
"roll": "Roll",
|
||||
|
||||
"delete-confirm": "Are you sure you wish to delete this token? It will not be recoverable.",
|
||||
"roll-confirm": "Are you sure you wish to regenerate this token? The old token will be immediately revoked and will not be recoverable."
|
||||
"token-on-save": "Token will be generated once form is saved"
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"zero-is-disabled": "Enter 0 to disable this restriction",
|
||||
"chat-settings": "Chat Settings",
|
||||
"disable": "Disable chat",
|
||||
"disable-editing": "Disable chat message editing/deletion",
|
||||
"disable-editing-help": "Administrators and global moderators are exempt from this restriction",
|
||||
"max-length": "Maximum length of chat messages",
|
||||
"max-chat-room-name-length": "Maximum length of chat room names",
|
||||
"max-room-size": "Maximum number of users in chat rooms",
|
||||
"delay": "Time between chat messages (ms)",
|
||||
"notification-delay": "Notification delay for chat messages",
|
||||
"notification-delay-help": "Additional messages sent between this time are collated, and the user is notified once per delay period. Set this to 0 to disable the delay.",
|
||||
"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": "Time between chat messages in milliseconds",
|
||||
"notification-delay": "Notification delay for chat messages. (0 for no delay)",
|
||||
"restrictions.seconds-edit-after": "Number of seconds a chat message will remain editable. (0 disabled)",
|
||||
"restrictions.seconds-delete-after": "Number of seconds a chat message will remain deletable. (0 disabled)"
|
||||
}
|
||||
@@ -5,18 +5,14 @@
|
||||
"from": "From Name",
|
||||
"from-help": "The from name to display in the email.",
|
||||
|
||||
"confirmation-settings": "Confirmation",
|
||||
"confirmation.expiry": "Hours to keep email confirmation link valid",
|
||||
|
||||
"smtp-transport": "SMTP Transport",
|
||||
"smtp-transport.enabled": "Enable SMTP Transport",
|
||||
"smtp-transport.enabled": "Use an external email server to send emails",
|
||||
"smtp-transport-help": "You can select from a list of well-known services or enter a custom one.",
|
||||
"smtp-transport.service": "Select a service",
|
||||
"smtp-transport.service-custom": "Custom Service",
|
||||
"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 <a href=\"https://myaccount.google.com/apppasswords\">App Passwords <i class=\"fa fa-external-link\"></i></a> page.",
|
||||
"smtp-transport.gmail-warning2": "For more information about this workaround, <a href=\"https://nodemailer.com/usage/using-gmail/\">please consult this NodeMailer article <i class=\"fa fa-external-link\"></i></a> on the issue. An alternative would be to utilise a third-party emailer plugin such as SendGrid, Mailgun, etc. <a href=\"../extend/plugins\">Browse available plugins here</a>.",
|
||||
"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": "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": "There have been reports of the Gmail service not working on accounts with heightened security. In those scenarios, you will have to <a href=\"https://www.google.com/settings/security/lesssecureapps\">configure your GMail account to allow less secure apps</a>.",
|
||||
"smtp-transport.gmail-warning2": "For more information about this workaround, <a href=\"https://nodemailer.com/usage/using-gmail/\">please consult this NodeMailer article on the issue.</a> An alternative would be to utilise a third-party emailer plugin such as SendGrid, Mailgun, etc. <a href=\"../extend/plugins\">Browse available plugins here</a>.",
|
||||
"smtp-transport.host": "SMTP Host",
|
||||
"smtp-transport.port": "SMTP Port",
|
||||
"smtp-transport.security": "Connection security",
|
||||
@@ -40,13 +36,6 @@
|
||||
"subscriptions.disable": "Disable email digests",
|
||||
"subscriptions.hour": "Digest Hour",
|
||||
"subscriptions.hour-help": "Please enter a number representing the hour to send scheduled email digests (e.g. <code>0</code> for midnight, <code>17</code> for 5:00pm). Keep in mind that this is the hour according to the server itself, and may not exactly match your system clock.<br /> The approximate server time is: <span id=\"serverTime\"></span><br /> The next daily digest is scheduled to be sent <span id=\"nextDigestTime\"></span>",
|
||||
"notifications.remove-images": "Remove images from email notifications",
|
||||
"require-email-address": "Require new users to specify an email address",
|
||||
"require-email-address-warning": "By default, users can opt-out of entering an email address by leaving the field blank. Enabling this option means new users will have to enter <strong>and confirm</strong> an email address in order to proceed with registration and subsequent access to the forum. <strong>It does not ensure user will enter a real email address, nor even an address they own.</strong>",
|
||||
"send-validation-email": "Send validation emails when an email is added or changed",
|
||||
"include-unverified-emails": "Send emails to recipients who have not explicitly confirmed their emails",
|
||||
"include-unverified-warning": "By default, users with emails associated with their account have already been verified, but there are situations where this is not the case (e.g. SSO logins, grandfathered users, etc). <strong>Enable this setting at your own risk</strong> – sending emails to unverified addresses may be a violation of regional anti-spam laws.",
|
||||
"prompt": "Prompt users to enter or confirm their emails",
|
||||
"prompt-help": "If a user does not have an email set, or their email is not confirmed, a warning will be shown on screen.",
|
||||
"sendEmailToBanned": "Send emails to users even if they have been banned"
|
||||
}
|
||||
"notifications.settings": "Email notification settings",
|
||||
"notifications.remove-images": "Remove images from email notifications"
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
{
|
||||
"general-settings": "General Settings",
|
||||
"on-this-page": "On this page:",
|
||||
"site-settings": "اعدادات الموقع",
|
||||
"title": "عنوان الموقع",
|
||||
"title.short": "عنوان قصير",
|
||||
"title.short-placeholder": "ان لم تقم بكتابة عنوان مختصر, سيتم استخدام عنوان الموقع الكلي",
|
||||
"title.url": "Title Link URL",
|
||||
"title.url": "الرابط",
|
||||
"title.url-placeholder": "The URL of the site title",
|
||||
"title.url-help": "When the title is clicked, send users to this address. If left blank, user will be sent to the forum index. Note: This is not the external URL used in emails, etc. That is set by the <code>url</code> property in config.json",
|
||||
"title.url-help": "When the title is clicked, send users to this address. If left blank, user will be sent to the forum index.",
|
||||
"title.name": "اسم المنتدي",
|
||||
"title.show-in-header": "Show Site Title in Header",
|
||||
"browser-title": "عنوان المتصفح",
|
||||
@@ -18,13 +16,13 @@
|
||||
"description": "وصف الموقع",
|
||||
"keywords": "الكلمات الدليله للموقع",
|
||||
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
||||
"logo-and-icons": "Site Logo & Icons",
|
||||
"logo": "شعار الموقع",
|
||||
"logo.image": "صورة",
|
||||
"logo.image-placeholder": "Path to a logo to display on forum header",
|
||||
"logo.upload": "رفع",
|
||||
"logo.url": "Logo Link URL",
|
||||
"logo.url": "الرابط",
|
||||
"logo.url-placeholder": "The URL of the site logo",
|
||||
"logo.url-help": "When the logo is clicked, send users to this address. If left blank, user will be sent to the forum index. <br> Note: This is not the external URL used in emails, etc. That is set by the <code>url</code> property in config.json",
|
||||
"logo.url-help": "When the logo is clicked, send users to this address. If left blank, user will be sent to the forum index.",
|
||||
"logo.alt-text": "نص بديل",
|
||||
"log.alt-text-placeholder": "Alternative text for accessibility",
|
||||
"favicon": "صورة المفضله",
|
||||
@@ -37,16 +35,10 @@
|
||||
"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.",
|
||||
"outgoing-links": "Outgoing Links",
|
||||
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
||||
"search": "Search",
|
||||
"search-default-in": "Search In",
|
||||
"search-default-in-quick": "Quick Search In",
|
||||
"search-default-sort-by": "Sort by",
|
||||
"search-default-sort-by": "الترتيب الافتراضي للبحث",
|
||||
"outgoing-links.whitelist": "Domains to whitelist for bypassing the warning page",
|
||||
"site-colors": "Site Color Metadata",
|
||||
"theme-color": "لون الثيم",
|
||||
"background-color": "لون الخلفية",
|
||||
"background-color-help": "Color used for splash screen background when website is installed as a PWA",
|
||||
"undo-timeout": "Undo Timeout",
|
||||
"undo-timeout-help": "Some operations such as moving topics will allow for the moderator to undo their action within a certain timeframe. Set to 0 to disable undo completely.",
|
||||
"topic-tools": "Topic Tools"
|
||||
}
|
||||
"background-color-help": "Color used for splash screen background when website is installed as a PWA"
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"settings": "Settings",
|
||||
"guest-settings": "Guest Settings",
|
||||
"handles.enabled": "Allow guest handles",
|
||||
"handles.enabled-help": "This option exposes a new field that allows guests to pick a name to associate with each post they make. If disabled, they will simply be called \"Guest\"",
|
||||
"topic-views.enabled": "Allow guests to increase topic view counts",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"navigation": "Navigation",
|
||||
"icon": "Icon:",
|
||||
"change-icon": "change",
|
||||
"route": "Route:",
|
||||
@@ -12,8 +11,6 @@
|
||||
"properties": "Properties:",
|
||||
"groups": "Groups:",
|
||||
"open-new-window": "Open in a new window",
|
||||
"dropdown": "Dropdown",
|
||||
"dropdown-placeholder": "Place your dropdown menu items below, ie: <br/><li><a class="dropdown-item" href="https://myforum.com">Link 1</a></li>",
|
||||
|
||||
"btn.delete": "Delete",
|
||||
"btn.disable": "Disable",
|
||||
@@ -23,4 +20,4 @@
|
||||
"custom-route": "Custom Route",
|
||||
"core": "core",
|
||||
"plugin": "plugin"
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,5 @@
|
||||
"notifications": "Notifications",
|
||||
"welcome-notification": "Welcome Notification",
|
||||
"welcome-notification-link": "Welcome Notification Link",
|
||||
"welcome-notification-uid": "Welcome Notification User (UID)",
|
||||
"post-queue-notification-uid": "Post Queue User (UID)"
|
||||
"welcome-notification-uid": "Welcome Notification User (UID)"
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
{
|
||||
"pagination": "Pagination Settings",
|
||||
"enable": "Paginate topics and posts instead of using infinite scroll.",
|
||||
"posts": "Post Pagination",
|
||||
"topics": "Topic Pagination",
|
||||
"posts-per-page": "Posts per Page",
|
||||
"max-posts-per-page": "Maximum posts per page",
|
||||
"categories": "Category Pagination",
|
||||
"topics-per-page": "Topics per Page",
|
||||
"max-topics-per-page": "Maximum topics per page",
|
||||
"categories-per-page": "Categories per page"
|
||||
"max-topics-per-page": "Maximum topics per page"
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"general": "General",
|
||||
"sorting": "Post Sorting",
|
||||
"sorting.post-default": "Default Post Sorting",
|
||||
"sorting.oldest-to-newest": "Oldest to Newest",
|
||||
@@ -10,6 +9,7 @@
|
||||
"length": "Post Length",
|
||||
"post-queue": "Post Queue",
|
||||
"restrictions": "Posting Restrictions",
|
||||
"restrictions-new": "New User Restrictions",
|
||||
"restrictions.post-queue": "Enable post queue",
|
||||
"restrictions.post-queue-rep-threshold": "Reputation required to bypass post queue",
|
||||
"restrictions.groups-exempt-from-post-queue": "Select groups that should be exempt from the post queue",
|
||||
@@ -17,13 +17,18 @@
|
||||
"restrictions.post-queue-help": "Enabling post queue will put the posts of new users in a queue for approval",
|
||||
"restrictions-new.post-queue-help": "Enabling new user restrictions will set restrictions on posts created by new users",
|
||||
"restrictions.seconds-between": "Number of seconds between posts",
|
||||
"restrictions.seconds-between-new": "Seconds between posts for new users",
|
||||
"restrictions.rep-threshold": "Reputation threshold before these restrictions are lifted",
|
||||
"restrictions.seconds-before-new": "Seconds before a new user can make their first post",
|
||||
"restrictions.seconds-edit-after": "Number of seconds a post remains editable (set to 0 to disable)",
|
||||
"restrictions.seconds-delete-after": "Number of seconds a post remains deletable (set to 0 to disable)",
|
||||
"restrictions.replies-no-delete": "Number of replies after users are disallowed to delete their own topics (set to 0 to disable)",
|
||||
"restrictions.title-length": "Title Length",
|
||||
"restrictions.post-length": "Post Length",
|
||||
"restrictions.min-title-length": "Minimum Title Length",
|
||||
"restrictions.max-title-length": "Maximum Title Length",
|
||||
"restrictions.min-post-length": "Minimum Post Length",
|
||||
"restrictions.max-post-length": "Maximum Post Length",
|
||||
"restrictions.days-until-stale": "Days until topic is considered stale",
|
||||
"restrictions.stale-help": "If a topic is considered \"stale\", then a warning will be shown to users who attempt to reply to that topic. (set to 0 to disable)",
|
||||
"restrictions.stale-help": "If a topic is considered \"stale\", then a warning will be shown to users who attempt to reply to that topic.",
|
||||
"timestamp": "Timestamp",
|
||||
"timestamp.cut-off": "Date cut-off (in days)",
|
||||
"timestamp.cut-off-help": "Dates & times will be shown in a relative manner (e.g. \"3 hours ago\" / \"5 days ago\"), and localised into various\n\t\t\t\t\tlanguages. After a certain point, this text can be switched to display the localised date itself\n\t\t\t\t\t(e.g. 5 Nov 2016 15:30).<br /><em>(Default: <code>30</code>, or one month). Set to 0 to always display dates, leave blank to always display relative times.</em>",
|
||||
@@ -35,26 +40,22 @@
|
||||
"teaser.last-post": "Last – Show the latest post, including the original post, if no replies",
|
||||
"teaser.last-reply": "Last – Show the latest reply, or a \"No replies\" placeholder if no replies",
|
||||
"teaser.first": "First",
|
||||
"showPostPreviewsOnHover": "Show a preview of posts when mouse overed",
|
||||
"unread-and-recent": "Unread & Recent Settings",
|
||||
"unread": "Unread Settings",
|
||||
"unread.cutoff": "Unread cutoff days",
|
||||
"unread.min-track-last": "Minimum posts in topic before tracking last read",
|
||||
"recent": "Recent Settings",
|
||||
"recent.max-topics": "Maximum topics on /recent",
|
||||
"recent.categoryFilter.disable": "Disable filtering of topics in ignored categories on the /recent page",
|
||||
"signature": "Signature Settings",
|
||||
"signature.disable": "Disable signatures",
|
||||
"signature.no-links": "Disable links in signatures",
|
||||
"signature.no-images": "Disable images in signatures",
|
||||
"signature.hide-duplicates": "Hide duplicate signatures in topics",
|
||||
"signature.max-length": "Maximum Signature Length",
|
||||
"composer": "Composer Settings",
|
||||
"composer-help": "The following settings govern the functionality and/or appearance of the post composer shown\n\t\t\t\tto users when they create new topics, or reply to existing topics.",
|
||||
"composer.show-help": "Show \"Help\" tab",
|
||||
"composer.enable-plugin-help": "Allow plugins to add content to the help tab",
|
||||
"composer.custom-help": "Custom Help Text",
|
||||
"backlinks": "Backlinks",
|
||||
"backlinks.enabled": "Enable topic backlinks",
|
||||
"backlinks.help": "If a post references another topic, a link back to the post will be inserted into the referenced topic at that point in time.",
|
||||
"ip-tracking": "IP Tracking",
|
||||
"ip-tracking.each-post": "Track IP Address for each post",
|
||||
"enable-post-history": "Enable Post History"
|
||||
|
||||
@@ -4,14 +4,9 @@
|
||||
"disable-down-voting": "Disable Down Voting",
|
||||
"votes-are-public": "All Votes Are Public",
|
||||
"thresholds": "Activity Thresholds",
|
||||
"min-rep-upvote": "Minimum reputation to upvote posts",
|
||||
"upvotes-per-day": "Upvotes per day (set to 0 for unlimited upvotes)",
|
||||
"upvotes-per-user-per-day": "Upvotes per user per day (set to 0 for unlimited upvotes)",
|
||||
"min-rep-downvote": "Minimum reputation to downvote posts",
|
||||
"downvotes-per-day": "Downvotes per day (set to 0 for unlimited downvotes)",
|
||||
"downvotes-per-user-per-day": "Downvotes per user per day (set to 0 for unlimited downvotes)",
|
||||
"min-rep-chat": "Minimum reputation to send chat messages",
|
||||
"min-rep-post-links": "Minimum reputation to post links",
|
||||
"min-rep-flag": "Minimum reputation to flag posts",
|
||||
"min-rep-website": "Minimum reputation to add \"Website\" to user profile",
|
||||
"min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile",
|
||||
@@ -21,12 +16,5 @@
|
||||
|
||||
"flags": "Flag Settings",
|
||||
"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.auto-flag-on-downvote-threshold": "Number of downvotes to auto flag posts (Set to 0 to disable, default: 0)",
|
||||
"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",
|
||||
"flags.action.nothing": "Do nothing",
|
||||
"flags.action.rescind": "Rescind the notification sent to moderators/administrators"
|
||||
"flags.limit-per-target-placeholder": "Default: 0"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"post-sharing": "Post Sharing",
|
||||
"info-plugins-additional": "Plugins can add additional networks for sharing posts."
|
||||
"info-plugins-additional": "Plugins can add additional networks for sharing posts.",
|
||||
"save-success": "Successfully saved Post Sharing Networks!"
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"tag": "Tag Settings",
|
||||
"link-to-manage": "Manage Tags",
|
||||
"system-tags": "System Tags",
|
||||
"system-tags-help": "Only privileged users will be able to use these tags.",
|
||||
"tags-per-topic": "Tags per topic",
|
||||
"min-per-topic": "Minimum Tags per Topic",
|
||||
"max-per-topic": "Maximum Tags per Topic",
|
||||
"min-length": "Minimum Tag Length",
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
{
|
||||
"posts": "المشاركات",
|
||||
"orphans": "Orphaned Files",
|
||||
"allow-files": "السماح للأعضاء بتحميل الملفات الإعتيادية",
|
||||
"private": "جعل الملفات التي تم رفعها خاصة",
|
||||
"strip-exif-data": "Strip EXIF Data",
|
||||
"preserve-orphaned-uploads": "Keep uploaded files on disk after a post is purged",
|
||||
"orphanExpiryDays": "Days to keep orphaned files",
|
||||
"orphanExpiryDays-help": "After this many days, orphaned uploads will be deleted from the file system.<br />Set 0 or leave blank to disable.",
|
||||
"private-extensions": "File extensions to make private",
|
||||
"private-uploads-extensions-help": "Enter comma-separated list of file extensions to make private here (e.g. <code>pdf,xls,doc</code>). An empty list means all files are private.",
|
||||
"resize-image-width-threshold": "Resize images if they are wider than specified width",
|
||||
@@ -24,9 +21,6 @@
|
||||
"topic-thumb-size": "حجم الصورة المصغرة للموضوع",
|
||||
"allowed-file-extensions": "إمتدادات الملفات المسموح بها",
|
||||
"allowed-file-extensions-help": "أدخل قائمة بامتدادات الملفات مفصولة بفواصل (مثال: <code>pdf,xls,doc</code>). القائمة الفارغة تعني أن كل الامتدادات مسموح بها.",
|
||||
"upload-limit-threshold": "Rate limit user uploads to:",
|
||||
"upload-limit-threshold-per-minute": "Per %1 Minute",
|
||||
"upload-limit-threshold-per-minutes": "Per %1 Minutes",
|
||||
"profile-avatars": "الصورة الرمزية للملف الشخصي",
|
||||
"allow-profile-image-uploads": "السماح للأعضاء برفع الصور الرمزية",
|
||||
"convert-profile-image-png": "تحويل إمتداد الصور الرمزية المرفوعه الى PNG",
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{
|
||||
"authentication": "المصادقة",
|
||||
"require-email-confirmation": "يطلب تأكيد البريد الإلكتروني",
|
||||
"email-confirm-interval": "لا يمكن للمستخدم إعادة إرسال رسالة تأكيد البريد الالكتروني حتى مرور",
|
||||
"email-confirm-interval2": "minutes have elapsed",
|
||||
"email-confirm-email2": "دقائق",
|
||||
"allow-login-with": "السماح بتسجيل الدخول باستخدام",
|
||||
"allow-login-with.username-email": "اسم المستخدم أو البريد الالكتروني",
|
||||
"allow-login-with.username": "اسم المستخدم فقط",
|
||||
"allow-login-with.email": "البريد الالكتروني فقط",
|
||||
"account-settings": "إعدادت الحساب",
|
||||
"gdpr-enabled": "Enable GDPR consent collection",
|
||||
"gdpr-enabled-help": "When enabled, all new registrants will be required to explicitly give consent for data collection and usage under the <a href=\"https://ec.europa.eu/info/priorities/justice-and-fundamental-rights/data-protection/2018-reform-eu-data-protection-rules/eu-data-protection-rules_en\">General Data Protection Regulation (GDPR)</a>. <strong>Note</strong>: Enabling GDPR does not force pre-existing users to provide consent. To do so, you will need to install the GDPR plugin.",
|
||||
"gdpr_enabled": "Enable GDPR consent collection",
|
||||
"gdpr_enabled_help": "When enabled, all new registrants will be required to explicitly give consent for data collection and usage under the <a href=\"https://ec.europa.eu/info/priorities/justice-and-fundamental-rights/data-protection/2018-reform-eu-data-protection-rules/eu-data-protection-rules_en\">General Data Protection Regulation (GDPR)</a>. <strong>Note</strong>: Enabling GDPR does not force pre-existing users to provide consent. To do so, you will need to install the GDPR plugin.",
|
||||
"disable-username-changes": "عدم السماح بتغيير اسم المستخدم",
|
||||
"disable-email-changes": "عدم السماح بتغيير البريد الالكتروني",
|
||||
"disable-password-changes": "عدم السماح بتغيير كلمة المرور",
|
||||
@@ -29,8 +31,6 @@
|
||||
"session-time-days": "Days",
|
||||
"session-time-seconds": "Seconds",
|
||||
"session-time-help": "These values are used to govern how long a user stays logged in when they check "Remember Me" on login. Note that only one of these values will be used. If there is no <i>seconds</i> value we fall back to <i>days</i>. If there is no <i>days</i> value we default to <i>14 days</i>.",
|
||||
"session-duration": "Session length if \"Remember Me\" is not checked (seconds)",
|
||||
"session-duration-help": "By default — or if set to <code>0</code> — a user will stay logged in for the duration of the session (e.g. however long the browser window/tab remains open). Set this value to explicitly invalidate the session after the specified number of seconds.",
|
||||
"online-cutoff": "Minutes after user is considered inactive",
|
||||
"online-cutoff-help": "If user performs no actions for this duration, they are considered inactive and they do not receive realtime updates.",
|
||||
"registration": "تسجيل المستخدم",
|
||||
@@ -59,7 +59,7 @@
|
||||
"max-about-me-length": "الحد الأعلى من الأحرف في حقل \"عني\"",
|
||||
"terms-of-use": "شروط استخدام المنتدى <small>(تترك فارغة لتعطيلها)</small>",
|
||||
"user-search": "بحث الأعضاء",
|
||||
"user-search-results-per-page": "Number of users to display in search results",
|
||||
"user-search-results-per-page": "عدد النتائج المراد عرضها",
|
||||
"default-user-settings": "إعدادات الأعضاء الافتراضية",
|
||||
"show-email": "عرض البريد الإلكتروني",
|
||||
"show-fullname": "عرض الاسم الكامل",
|
||||
@@ -71,7 +71,6 @@
|
||||
"digest-freq.off": "Off",
|
||||
"digest-freq.daily": "Daily",
|
||||
"digest-freq.weekly": "Weekly",
|
||||
"digest-freq.biweekly": "Bi-Weekly",
|
||||
"digest-freq.monthly": "Monthly",
|
||||
"email-chat-notifs": "Send an email if a new chat message arrives and I am not online",
|
||||
"email-post-notif": "Send an email when replies are made to topics I am subscribed to",
|
||||
@@ -79,14 +78,7 @@
|
||||
"follow-replied-topics": "Follow topics that you reply to",
|
||||
"default-notification-settings": "Default notification settings",
|
||||
"categoryWatchState": "Default category watch state",
|
||||
"categoryWatchState.tracking": "Tracking",
|
||||
"categoryWatchState.watching": "Watching",
|
||||
"categoryWatchState.notwatching": "Not Watching",
|
||||
"categoryWatchState.ignoring": "Ignoring",
|
||||
"restrictions-new": "New User Restrictions",
|
||||
"restrictions.rep-threshold": "Reputation threshold before these restrictions are lifted",
|
||||
"restrictions.seconds-between-new": "Seconds between posts for new users",
|
||||
"restrictions.seconds-before-new": "Seconds before a new user can make their first post",
|
||||
"restrictions.seconds-edit-after-new": "Number of seconds a post remains editable for new users (set to 0 to disable)",
|
||||
"restrictions.milliseconds-between-messages": "Time between chat messages for new users (ms)",
|
||||
"restrictions.groups-exempt-from-new-user-restrictions": "Select groups that should be exempt from the new user restrictions"
|
||||
"categoryWatchState.ignoring": "Ignoring"
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
{
|
||||
"category": "قسم",
|
||||
"subcategories": "قسم فرعي",
|
||||
"new-topic-button": "موضوع جديد",
|
||||
"new_topic_button": "موضوع جديد",
|
||||
"guest-login-post": "سجل الدخول للمشاركة",
|
||||
"no-topics": "<strong>لا توجد مواضيع في هذه القسم</strong>لم لا تحاول إنشاء موضوع؟<br />",
|
||||
"no_topics": "<strong>لا توجد مواضيع في هذه القسم</strong>لم لا تحاول إنشاء موضوع؟<br />",
|
||||
"browsing": "تصفح",
|
||||
"no-replies": "لم يرد أحد",
|
||||
"no-new-posts": "لا توجد مشاركات جديدة.",
|
||||
"no_replies": "لم يرد أحد",
|
||||
"no_new_posts": "لا توجد مشاركات جديدة.",
|
||||
"watch": "تابع",
|
||||
"ignore": "تجاهل",
|
||||
"watching": "متابع",
|
||||
"tracking": "Tracking",
|
||||
"not-watching": "لست متابع",
|
||||
"ignoring": "متجاهل",
|
||||
"watching.description": "Notify me of new topics.<br/>Show topics in unread & recent",
|
||||
"tracking.description": "Shows topics in unread & recent",
|
||||
"watching.description": "أظهر المواضيع في الغير مقروء و الحديث",
|
||||
"not-watching.description": "Do not show topics in unread, show in recent",
|
||||
"ignoring.description": "Do not show topics in unread & recent",
|
||||
"ignoring.description": "Do not show topics in unread and 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",
|
||||
"watched-categories": "الأقسام المُتابعة",
|
||||
"x-more-categories": "%1 more categories"
|
||||
"watched-categories": "الأقسام المُتابعة"
|
||||
}
|
||||
@@ -3,12 +3,10 @@
|
||||
"password-reset-requested": "Password Reset Requested!",
|
||||
"welcome-to": "مرحبًا بك في %1",
|
||||
"invite": "دعوة من %1",
|
||||
"greeting-no-name": "مرحبًا",
|
||||
"greeting-with-name": "مرحبًا بك يا %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. <strong>If you did not request this, no action is required on your part.</strong>",
|
||||
"email.verify.text3": "Once you confirm this email address, we will replace your current email address with this one (%1).",
|
||||
"email.verify.text1": "Your email address has changed!",
|
||||
"welcome.text1": "شكرًا على تسجيلك في %1!",
|
||||
"welcome.text2": "لتفعيل حسابك، نحتاج إلى التأكد من صحة عنوان البريد الإلكتروني الذي سجلت به.",
|
||||
"welcome.text3": "تم قبول نتسجيلك ، يمكنك الدخول باتسخدام اسم المستخدم و كلمة المرور.",
|
||||
@@ -22,9 +20,7 @@
|
||||
"reset.notify.subject": "تم تغيير كلمة المرور بنجاح",
|
||||
"reset.notify.text1": "نحيطك علما أن كلمة مرورك قد تم تغييرها في %1",
|
||||
"reset.notify.text2": "إن لم يكن لديك علم بهذا، المرجو إشعار مدبر النظام بأسرع مايمكن.",
|
||||
"digest.unread-rooms": "Unread rooms",
|
||||
"digest.room-name-unreadcount": "%1 (%2 unread)",
|
||||
"digest.latest-topics": "آخر المستجدات من %1",
|
||||
"digest.latest_topics": "آخر المستجدات من %1",
|
||||
"digest.top-topics": "Top topics from %1",
|
||||
"digest.popular-topics": "Popular topics from %1",
|
||||
"digest.cta": "انقر هنا لمشاهدة %1",
|
||||
@@ -36,8 +32,7 @@
|
||||
"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",
|
||||
"notif.chat.subject": "هناك محادثة جديدة من %1",
|
||||
"notif.chat.cta": "انقر هنا لمتابعة المحادثة",
|
||||
"notif.chat.unsub.info": "تم إرسال هذا الإشعار بوجودة محادثة جديدة وفقا لخيارات تسجيلك.",
|
||||
"notif.post.unsub.info": "تم إشعارك بهذه المشاركة بناءً على الخيارات التي سبق وأن حددتها.",
|
||||
@@ -51,8 +46,6 @@
|
||||
"unsub.cta": "انقر هنا لتغيير تلك الإعدادات",
|
||||
"unsubscribe": "unsubscribe",
|
||||
"unsub.success": "You will no longer receive emails from the <strong>%1</strong> 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 <a href=\"%2\">your user settings</a>.<br /><br />(error: <code>%1</code>)",
|
||||
"banned.subject": "You have been banned from %1",
|
||||
"banned.text1": "The user %1 has been banned from %2.",
|
||||
"banned.text2": "This ban will last until %1.",
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"invalid-data": "بيانات غير صحيحة",
|
||||
"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",
|
||||
"not-logged-in": "لم تقم بتسجيل الدخول",
|
||||
"account-locked": "تم حظر حسابك مؤقتًا.",
|
||||
"search-requires-login": "البحث في المنتدى يتطلب حساب - الرجاء تسجيل الدخول أو التسجيل",
|
||||
@@ -11,8 +9,6 @@
|
||||
"invalid-tid": "موضوع غير متواجد",
|
||||
"invalid-pid": "رد غير موجود",
|
||||
"invalid-uid": "مستخدم غير موجود",
|
||||
"invalid-mid": "Invalid Chat Message ID",
|
||||
"invalid-date": "A valid date must be provided",
|
||||
"invalid-username": "اسم المستخدم غير مقبول",
|
||||
"invalid-email": "البريد الاكتروني غير مقبول",
|
||||
"invalid-fullname": "Invalid Fullname",
|
||||
@@ -25,46 +21,36 @@
|
||||
"invalid-username-or-password": "المرجود تحديد اسم مستخدم و كلمة مرور",
|
||||
"invalid-search-term": "كلمة البحث غير صحيحة",
|
||||
"invalid-url": "Invalid URL",
|
||||
"invalid-event": "Invalid event: %1",
|
||||
"local-login-disabled": "Local login system has been disabled for non-privileged accounts.",
|
||||
"csrf-invalid": "لم تتمكن من تسجيل الدخول. هنالك أحتمال ان جلستك انتهت. رجاءًا حاول مرة اخرى.",
|
||||
"invalid-path": "Invalid path",
|
||||
"folder-exists": "Folder exists",
|
||||
"invalid-pagination-value": "رقم الصفحة غير صحيح ، يجب أن يكون بين %1 و %2 .",
|
||||
"username-taken": "اسم المستخدم مأخوذ",
|
||||
"email-taken": "البريد الالكتروني مأخوذ",
|
||||
"email-nochange": "The email entered is the same as the email already on file.",
|
||||
"email-invited": "Email was already invited",
|
||||
"email-not-confirmed": "Posting in some categories or topics is enabled once your email is confirmed, please click here to send a confirmation email.",
|
||||
"email-not-confirmed": "You are unable to post until your email is confirmed, please click here to confirm your email.",
|
||||
"email-not-confirmed-chat": "لا يمكنك الدردشة حتى تقوم بتأكيد بريدك الإلكتروني، الرجاء إضغط هنا لتأكيد بريدك اﻹلكتروني.",
|
||||
"email-not-confirmed-email-sent": "Your email has not been confirmed yet, please check your inbox for the confirmation email. You may not be able to post in some categories or chat until your email is confirmed.",
|
||||
"no-email-to-confirm": "Your account does not have an email set. An email is necessary for account recovery, and may be necessary for chatting and posting in some categories. Please click here to enter an email.",
|
||||
"user-doesnt-have-email": "User \"%1\" does not have an email set.",
|
||||
"email-not-confirmed-email-sent": "Your email has not been confirmed yet, please check your inbox for the confirmation email. You won't be able to post or chat until your email is confirmed.",
|
||||
"no-email-to-confirm": "هذا المنتدى يستلزم تفعيل بريدك الإلكتروني، انقر هنا من فضلك لإدخاله.",
|
||||
"email-confirm-failed": "لم نستطع تفعيل بريدك الإلكتروني، المرجو المحاولة لاحقًا.",
|
||||
"confirm-email-already-sent": "لقد تم ارسال بريد التأكيد، الرجاء اﻹنتظار 1% دقائق لإعادة اﻹرسال",
|
||||
"confirm-email-expired": "Confirmation email expired",
|
||||
"sendmail-not-found": "The sendmail executable could not be found, please ensure it is installed and executable by the user running NodeBB.",
|
||||
"digest-not-enabled": "This user does not have digests enabled, or the system default is not configured to send digests",
|
||||
"username-too-short": "اسم المستخدم قصير.",
|
||||
"username-too-long": "اسم المستخدم طويل",
|
||||
"password-too-long": "كلمة السر طويلة",
|
||||
"password-too-long": "كلمة السر طويلة ",
|
||||
"reset-rate-limited": "Too many password reset requests (rate limited)",
|
||||
"reset-same-password": "Please use a password that is different from your current one",
|
||||
"user-banned": "المستخدم محظور",
|
||||
"user-banned-reason": "Sorry, this account has been banned (Reason: %1)",
|
||||
"user-banned-reason-until": "Sorry, this account has been banned until %1 (Reason: %2)",
|
||||
"user-too-new": "عذرا, يجب أن تنتظر 1% ثواني قبل قيامك بأول مشاركة",
|
||||
"blacklisted-ip": "نأسف، لقد تم حظرك من استخدام وتصفح المنتدى. إذا كنت تعتقد أن هذا خطأ رجاءًا اتصل بالإدارة.",
|
||||
"cant-blacklist-self-ip": "You can't blacklist your own IP",
|
||||
"ban-expiry-missing": "رجاءًا ضع تاريخ نهاية الحظر.",
|
||||
"blacklisted-ip": "نأسف، لقد تم حظرك من استخدام وتصفح المنتدى. إذا كنت تعتقد أن هذا خطأ رجاءًا اتصل بالإدارة. ",
|
||||
"ban-expiry-missing": "رجاءًا ضع تاريخ نهاية الحظر. ",
|
||||
"no-category": "قائمة غير موجودة",
|
||||
"no-topic": "موضوع غير موجود",
|
||||
"no-post": "رد غير موجود",
|
||||
"no-group": "مجموعة غير موجودة",
|
||||
"no-user": "اسم مستخدم غير موجود",
|
||||
"no-teaser": "مقتطف غير موجود",
|
||||
"no-flag": "Flag does not exist",
|
||||
"no-chat-room": "Chat room does not exist",
|
||||
"no-privileges": "لاتملك الصلاحيات اللازمة للقيام بهذه العملية",
|
||||
"category-disabled": "قائمة معطلة",
|
||||
"topic-locked": "الموضوع مقفول",
|
||||
@@ -91,38 +77,19 @@
|
||||
"category-not-selected": "Category not selected.",
|
||||
"too-many-posts": "يسمح لك بالنشر مرة كل %1 ثانية - يرجى الإنتظار قبل النشر مجدداً",
|
||||
"too-many-posts-newbie": "As a new user, you can only post once every %1 second(s) until you have earned %2 reputation - please wait before posting again",
|
||||
"too-many-posts-newbie-minutes": "As a new user, you can only post once every %1 minute(s) until you have earned %2 reputation - please wait before posting again",
|
||||
"already-posting": "You are already posting",
|
||||
"tag-too-short": "Please enter a longer tag. Tags should contain at least %1 character(s)",
|
||||
"tag-too-long": "Please enter a shorter tag. Tags can't be longer than %1 character(s)",
|
||||
"tag-not-allowed": "Tag not allowed",
|
||||
"not-enough-tags": "Not enough tags. Topics must have at least %1 tag(s)",
|
||||
"too-many-tags": "Too many tags. Topics can't have more than %1 tag(s)",
|
||||
"cant-use-system-tag": "You can not use this system tag.",
|
||||
"cant-remove-system-tag": "You can not remove this system tag.",
|
||||
"still-uploading": "الرجاء الانتظار حتى يكتمل الرفع.",
|
||||
"file-too-big": "الحد الأقصى لرفع الملفات %1 كيلو بت. رجاءًا ارفع ملف أصغر",
|
||||
"guest-upload-disabled": "خاصية رفع الملفات غير مفعلة للزوار.",
|
||||
"cors-error": "Unable to upload image due to misconfigured CORS",
|
||||
"upload-ratelimit-reached": "You have uploaded too many files at one time. Please try again later.",
|
||||
"upload-error-fallback": "Unable to upload image — %1",
|
||||
"scheduling-to-past": "Please select a date in the future.",
|
||||
"invalid-schedule-date": "Please enter a valid date and time.",
|
||||
"cant-pin-scheduled": "Scheduled topics cannot be (un)pinned.",
|
||||
"cant-merge-scheduled": "Scheduled topics cannot be merged.",
|
||||
"cant-move-posts-to-scheduled": "Can't move posts to a scheduled topic.",
|
||||
"cant-move-from-scheduled-to-existing": "Can't move posts from a scheduled topic to an existing topic.",
|
||||
"already-bookmarked": "You have already bookmarked this post",
|
||||
"already-unbookmarked": "You have already unbookmarked this post",
|
||||
"cant-ban-other-admins": "لايمكن حظر مدبر نظام آخر.",
|
||||
"cant-mute-other-admins": "You can't mute other admins!",
|
||||
"user-muted-for-hours": "You have been muted, you will be able to post in %1 hour(s)",
|
||||
"user-muted-for-minutes": "You have been muted, you will be able to post in %1 minute(s)",
|
||||
"cant-make-banned-users-admin": "You can't make banned users admin.",
|
||||
"cant-remove-last-admin": "رجاءًا ، أضف مدير أخر قبل حذف صلاحيات الإدارة من حسابك.",
|
||||
"account-deletion-disabled": "Account deletion is disabled",
|
||||
"cant-delete-admin": "رجاءًا أزل صلاحيات الإدارة قبل حذف الحساب.",
|
||||
"already-deleting": "Already deleting",
|
||||
"cant-delete-admin": "رجاءًا أزل صلاحيات الإدارة قبل حذف الحساب. ",
|
||||
"invalid-image": "Invalid image",
|
||||
"invalid-image-type": "نوع الصورة غير مدعوم. الأنواع المدعومة هي : %1",
|
||||
"invalid-image-extension": "امتداد الصورة غير مدعوم.",
|
||||
@@ -139,8 +106,6 @@
|
||||
"group-already-requested": "سبق وتم تسجيل طلب العضوية",
|
||||
"group-join-disabled": "You are not able to join this group at this time",
|
||||
"group-leave-disabled": "You are not able to leave this group at this time",
|
||||
"group-user-not-pending": "User does not have a pending request to join this group.",
|
||||
"gorup-user-not-invited": "User has not been invited to join this group.",
|
||||
"post-already-deleted": "سبق وتم حذف هذا الرد",
|
||||
"post-already-restored": "سبق وتم إلغاء حذف هذا الرد",
|
||||
"topic-already-deleted": "سبق وتم حذف هذا الموضوع",
|
||||
@@ -150,7 +115,7 @@
|
||||
"invalid-file": "ملف غير مقبول",
|
||||
"uploads-are-disabled": "رفع الملفات غير مفعل",
|
||||
"signature-too-long": "عذرا، توقيعك يجب ألا يتجاوز %1 حرفًا.",
|
||||
"about-me-too-long": "نأسف، ( عني ) لا يمكن أن يكون أكثر من %1 حرف.",
|
||||
"about-me-too-long": "نأسف، ( عني ) لا يمكن أن يكون أكثر من %1 حرف. ",
|
||||
"cant-chat-with-yourself": "لايمكنك فتح محادثة مع نفسك",
|
||||
"chat-restricted": "هذا المستخدم عطل المحادثات الواردة عليه. يجب أن يتبعك حتى تتمكن من فتح محادثة معه.",
|
||||
"chat-disabled": "نظام المحادثة معطل.",
|
||||
@@ -158,37 +123,27 @@
|
||||
"invalid-chat-message": "الرسالة غير صالحة.",
|
||||
"chat-message-too-long": "Chat messages can not be longer than %1 characters.",
|
||||
"cant-edit-chat-message": "غير مصرح لك بتعديل الرسالة.",
|
||||
"cant-remove-last-user": "لأيمكنك إزالت اخر مستخدم.",
|
||||
"cant-delete-chat-message": "غير مصرح لك بحذف الرسالة.",
|
||||
"chat-edit-duration-expired": "You are only allowed to edit chat messages for %1 second(s) after posting",
|
||||
"chat-delete-duration-expired": "You are only allowed to delete chat messages for %1 second(s) after posting",
|
||||
"chat-deleted-already": "This chat message has already been deleted.",
|
||||
"chat-restored-already": "This chat message has already been restored.",
|
||||
"chat-room-does-not-exist": "Chat room does not exist.",
|
||||
"cant-add-users-to-chat-room": "Can't add users to chat room.",
|
||||
"cant-remove-users-from-chat-room": "Can't remove users from chat room.",
|
||||
"chat-room-name-too-long": "Chat room name too long. Names can't be longer than %1 characters.",
|
||||
"already-voting-for-this-post": "لقد شاركت بالتصويت ، ألا تذكر؟",
|
||||
"reputation-system-disabled": "نظام السمعة معطل",
|
||||
"downvoting-disabled": "التصويتات السلبية معطلة",
|
||||
"not-enough-reputation-to-chat": "You need %1 reputation to chat",
|
||||
"not-enough-reputation-to-upvote": "You need %1 reputation to upvote",
|
||||
"not-enough-reputation-to-downvote": "You need %1 reputation to downvote",
|
||||
"not-enough-reputation-to-post-links": "You need %1 reputation to post links",
|
||||
"not-enough-reputation-to-flag": "You need %1 reputation to flag this post",
|
||||
"not-enough-reputation-min-rep-website": "You need %1 reputation to add a website",
|
||||
"not-enough-reputation-min-rep-aboutme": "You need %1 reputation to add an about me",
|
||||
"not-enough-reputation-min-rep-signature": "You need %1 reputation to add a signature",
|
||||
"not-enough-reputation-min-rep-profile-picture": "You need %1 reputation to add a profile picture",
|
||||
"not-enough-reputation-min-rep-cover-picture": "You need %1 reputation to add a cover picture",
|
||||
"not-enough-reputation-to-downvote": "ليس لديك سمعة تكفي لإضافة صوت سلبي لهذا الموضوع",
|
||||
"not-enough-reputation-to-flag": "ليس لديك سمعة تكفي للإشعار بموضوع مخل",
|
||||
"not-enough-reputation-min-rep-website": "You do not have enough reputation to add a website",
|
||||
"not-enough-reputation-min-rep-aboutme": "You do not have enough reputation to add an about me",
|
||||
"not-enough-reputation-min-rep-signature": "You do not have enough reputation to add a signature",
|
||||
"not-enough-reputation-min-rep-profile-picture": "You do not have enough reputation to add a profile picture",
|
||||
"not-enough-reputation-min-rep-cover-picture": "You do not have enough reputation to add a cover picture",
|
||||
"post-already-flagged": "You have already flagged this post",
|
||||
"user-already-flagged": "You have already flagged this user",
|
||||
"post-flagged-too-many-times": "This post has been flagged by others already",
|
||||
"user-flagged-too-many-times": "This user has been flagged by others already",
|
||||
"cant-flag-privileged": "You are not allowed to flag the profiles or content of privileged users (moderators/global moderators/admins)",
|
||||
"cant-locate-flag-report": "Cannot locate flag report",
|
||||
"self-vote": "You cannot vote on your own post",
|
||||
"too-many-upvotes-today": "You can only upvote %1 times a day",
|
||||
"too-many-upvotes-today-user": "You can only upvote a user %1 times a day",
|
||||
"too-many-downvotes-today": "You can only downvote %1 times a day",
|
||||
"too-many-downvotes-today-user": "You can only downvote a user %1 times a day",
|
||||
"reload-failed": "المنتدى واجه مشكلة أثناء إعادة التحميل: \"%1\". سيواصل المنتدى خدمة العملاء السابقين لكن يجب عليك إلغاء أي تغيير قمت به قبل إعادة التحميل.",
|
||||
@@ -203,12 +158,9 @@
|
||||
"not-in-room": "المستخدم غير موجود في الغرفة.",
|
||||
"cant-kick-self": "لا يمكنك طرد نفسك من المجموعة.",
|
||||
"no-users-selected": "لا يوجد مستخدم محدد.",
|
||||
"no-groups-selected": "No group(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route",
|
||||
"invalid-session": "Invalid Session",
|
||||
"invalid-session-text": "It looks like your login session is no longer active. Please refresh this page.",
|
||||
"session-mismatch": "Session Mismatch",
|
||||
"session-mismatch-text": "It looks like your login session no longer matches with the server. Please refresh this page.",
|
||||
"invalid-session": "Session Mismatch",
|
||||
"invalid-session-text": "يبدو أن فترة التسجيل لم تعد قائمة او هي غير مطابقة مع الخادم. يرجى إعادة تحميل هذه الصفحة.",
|
||||
"no-topics-selected": "No topics selected!",
|
||||
"cant-move-to-same-topic": "Can't move post to same topic!",
|
||||
"cant-move-topic-to-same-category": "Can't move topic to the same category!",
|
||||
@@ -218,22 +170,5 @@
|
||||
"already-blocked": "This user is already blocked",
|
||||
"already-unblocked": "This user is already unblocked",
|
||||
"no-connection": "There seems to be a problem with your internet connection",
|
||||
"socket-reconnect-failed": "Unable to reach the server at this time. Click here to try again, or try again later",
|
||||
"plugin-not-whitelisted": "Unable to install plugin – only plugins whitelisted by the NodeBB Package Manager can be installed via the ACP",
|
||||
"plugins-set-in-configuration": "You are not allowed to change plugin state as they are defined at runtime (config.json, environmental variables or terminal arguments), please modify the configuration instead.",
|
||||
"theme-not-set-in-configuration": "When defining active plugins in configuration, changing themes requires adding the new theme to the list of active plugins before updating it in the ACP",
|
||||
"topic-event-unrecognized": "Topic event '%1' unrecognized",
|
||||
"cant-set-child-as-parent": "Can't set child as parent category",
|
||||
"cant-set-self-as-parent": "Can't set self as parent category",
|
||||
"api.master-token-no-uid": "A master token was received without a corresponding `_uid` in the request body",
|
||||
"api.400": "Something was wrong with the request payload you passed in.",
|
||||
"api.401": "A valid login session was not found. Please log in and try again.",
|
||||
"api.403": "You are not authorised to make this call",
|
||||
"api.404": "Invalid API call",
|
||||
"api.426": "HTTPS is required for requests to the write api, please re-send your request via HTTPS",
|
||||
"api.429": "You have made too many requests, please try again later",
|
||||
"api.500": "An unexpected error was encountered while attempting to service your request.",
|
||||
"api.501": "The route you are trying to call is not implemented yet, please try again tomorrow",
|
||||
"api.503": "The route you are trying to call is not currently available due to a server configuration",
|
||||
"api.reauth-required": "The resource you are trying to access requires (re-)authentication."
|
||||
"plugin-not-whitelisted": "Unable to install plugin – only plugins whitelisted by the NodeBB Package Manager can be installed via the ACP"
|
||||
}
|
||||
@@ -1,38 +1,31 @@
|
||||
{
|
||||
"state": "الحالة",
|
||||
"report": "Report",
|
||||
"reports": "Reports",
|
||||
"first-reported": "First Reported",
|
||||
"no-flags": "Hooray! No flags found.",
|
||||
"x-flags-found": "%1 flag(s) found.",
|
||||
"assignee": "المحال إليه",
|
||||
"update": "تحديث",
|
||||
"updated": "تم التحديث",
|
||||
"resolved": "Resolved",
|
||||
"report-added": "Added",
|
||||
"report-rescinded": "Rescinded",
|
||||
"target-purged": "The content this flag referred to has been purged and is no longer available.",
|
||||
"target-aboutme-empty": "This user has no "About Me" set.",
|
||||
|
||||
"graph-label": "Daily Flags",
|
||||
"quick-filters": "Quick Filters",
|
||||
"filter-active": "There are one or more filters active in this list of flags",
|
||||
"filter-reset": "ازالة الفلاتر",
|
||||
"filters": "خيارات الفلتر",
|
||||
"filter-reporterId": "Reporter",
|
||||
"filter-targetUid": "Reportee",
|
||||
"filter-reporterId": "Reporter UID",
|
||||
"filter-targetUid": "Flagged UID",
|
||||
"filter-type": "عنوان العلامة",
|
||||
"filter-type-all": "كل المحتوي",
|
||||
"filter-type-post": "مشاركة",
|
||||
"filter-type-user": "مستخدم",
|
||||
"filter-state": "الحالة",
|
||||
"filter-assignee": "Assignee",
|
||||
"filter-assignee": "Assignee UID",
|
||||
"filter-cid": "Category",
|
||||
"filter-quick-mine": "Assigned to me",
|
||||
"filter-cid-all": "All categories",
|
||||
"apply-filters": "Apply Filters",
|
||||
"more-filters": "More Filters",
|
||||
"fewer-filters": "Fewer Filters",
|
||||
|
||||
"quick-actions": "اجراءات سريعه",
|
||||
"flagged-user": "Flagged User",
|
||||
@@ -43,20 +36,16 @@
|
||||
"delete-post": "حذف المشاركة",
|
||||
"purge-post": "Purge Post",
|
||||
"restore-post": "استرجاع المشاركة",
|
||||
"delete": "Delete Flag",
|
||||
|
||||
"user-view": "مشاهدة الملف الشخصي",
|
||||
"user-edit": "تعديل الملف الشخصي",
|
||||
|
||||
"notes": "Flag Notes",
|
||||
"add-note": "اضافة ملاحظة",
|
||||
"edit-note": "Edit Note",
|
||||
"no-notes": "No shared notes.",
|
||||
"delete-note-confirm": "Are you sure you want to delete this flag note?",
|
||||
"delete-flag-confirm": "Are you sure you want to delete this flag?",
|
||||
"note-added": "Note Added",
|
||||
"note-deleted": "Note Deleted",
|
||||
"flag-deleted": "Flag Deleted",
|
||||
|
||||
"history": "Account & Flag History",
|
||||
"no-history": "No flag history.",
|
||||
@@ -86,10 +75,11 @@
|
||||
"modal-reason-custom": "Reason for reporting this content...",
|
||||
"modal-submit": "Submit Report",
|
||||
"modal-submit-success": "Content has been flagged for moderation.",
|
||||
"modal-submit-confirm": "Confirm Submission",
|
||||
"modal-submit-confirm-text": "You have a custom reason specified already. Are you sure you wish to submit via quick-report?",
|
||||
"modal-submit-confirm-text-help": "Submitting a quick report will overwrite any custom reasons defined.",
|
||||
|
||||
"bulk-actions": "Bulk Actions",
|
||||
"bulk-resolve": "Resolve Flag(s)",
|
||||
"bulk-success": "%1 flags updated",
|
||||
"flagged-timeago-readable": "Flagged <span class=\"timeago\" title=\"%1\"></span> (%2)",
|
||||
"auto-flagged": "[Auto Flagged] Received %1 downvotes."
|
||||
"bulk-success": "%1 flags updated"
|
||||
}
|
||||
@@ -4,28 +4,26 @@
|
||||
"buttons.close": "أغلق",
|
||||
"403.title": "غير مسموح بالدخول",
|
||||
"403.message": "يبدو أنك قد تعثرت على صفحة لا تمتلك الصلاحية للدخول إليها",
|
||||
"403.login": "Perhaps you should <a class=\"alert-link\" href='%1/login'>try logging in</a>?",
|
||||
"403.login": "ربما يجب عليك <a href='%1/login'>تسجل دخولك</a>.",
|
||||
"404.title": "لم يتم العثور",
|
||||
"404.message": "You seem to have stumbled upon a page that does not exist.<br/><div class=\"text-sm text-muted\">Return to the <a href='%1/'>home page</a>.</div>",
|
||||
"404.message": "الصفحة غير موجودة. العودة لـ <a href='%1/'>الرئيسية</a>",
|
||||
"500.title": "خطأ داخلي",
|
||||
"500.message": "عفوا! يبدو وكأنه شيء ذهب على نحو خاطئ!",
|
||||
"400.title": "طلب سيئ",
|
||||
"400.message": "It looks like this link is malformed, please double-check and try again.<br/><div class=\"text-sm text-muted\">Return to the <a href='%1/'>home page</a>.</div>",
|
||||
"400.message": "الرابط غير صحيح. رجاءًا تأكد من الرابط أو ارجع لـ <a href='%1/'>الرئيسية</a>",
|
||||
"register": "تسجيل",
|
||||
"login": "دخول",
|
||||
"please-log-in": "الرجاء تسجيل الدخول",
|
||||
"please_log_in": "الرجاء تسجيل الدخول",
|
||||
"logout": "تسجيل الخروج",
|
||||
"posting-restriction-info": "إضافة مشاركات جديد حكر على الأعضاء المسجلين، انقر هنا لتسجيل الدخول.",
|
||||
"welcome-back": "مرحبًا بعودتك",
|
||||
"you-have-successfully-logged-in": "تم سجيل الدخول بنجاح",
|
||||
"save-changes": "حفظ التغييرات",
|
||||
"posting_restriction_info": "إضافة مشاركات جديد حكر على الأعضاء المسجلين، انقر هنا لتسجيل الدخول.",
|
||||
"welcome_back": "مرحبًا بعودتك",
|
||||
"you_have_successfully_logged_in": "تم سجيل الدخول بنجاح",
|
||||
"save_changes": "حفظ التغييرات",
|
||||
"save": "حفظ",
|
||||
"create": "Create",
|
||||
"cancel": "Cancel",
|
||||
"close": "أغلق",
|
||||
"pagination": "الصفحات",
|
||||
"pagination.out-of": "%1 من %2",
|
||||
"pagination.enter-index": "Go to post index",
|
||||
"pagination.out_of": "%1 من %2",
|
||||
"pagination.enter_index": "أدخل الرقم التسلسلي",
|
||||
"header.admin": "مدير النظام",
|
||||
"header.categories": "الأقسام",
|
||||
"header.recent": "حديث",
|
||||
@@ -39,34 +37,23 @@
|
||||
"header.notifications": "التنبيهات",
|
||||
"header.search": "بحث",
|
||||
"header.profile": "ملف",
|
||||
"header.account": "Account",
|
||||
"header.navigation": "الاستكشاف",
|
||||
"header.manage": "Manage",
|
||||
"header.drafts": "Drafts",
|
||||
"notifications.loading": "تحميل التنبيهات",
|
||||
"chats.loading": "تحميل الدردشات",
|
||||
"drafts.loading": "Loading Drafts",
|
||||
"motd.welcome": "مرحبا بكم في NodeBB، منصة المناقشة المستقبلية.",
|
||||
"previouspage": "الصفحة السابقة",
|
||||
"nextpage": "الصفحة التالية",
|
||||
"alert.success": "نجاح",
|
||||
"alert.error": "خطأ",
|
||||
"alert.warning": "Warning",
|
||||
"alert.info": "Info",
|
||||
"alert.banned": "محظور",
|
||||
"alert.banned.message": "You have just been banned, your access is now restricted.",
|
||||
"alert.unbanned": "Unbanned",
|
||||
"alert.unbanned.message": "Your ban has been lifted.",
|
||||
"alert.banned.message": "لقد تم حظر حسابك. سيتم تسجيل الخروج.",
|
||||
"alert.unfollow": "أنت لا تتابع %1 بعد الآن!",
|
||||
"alert.follow": "أنت الآن تتابع %1!",
|
||||
"users": "الأعضاء",
|
||||
"topics": "المواضيع",
|
||||
"posts": "المشاركات",
|
||||
"x-posts": "<span class=\"formatted-number\">%1</span> posts",
|
||||
"x-topics": "<span class=\"formatted-number\">%1</span> topics",
|
||||
"x-reputation": "<span class=\"formatted-number\">%1</span> reputation",
|
||||
"x-posts": "%1 posts",
|
||||
"best": "الأفضل",
|
||||
"controversial": "Controversial",
|
||||
"votes": "Votes",
|
||||
"x-votes": "%1 votes",
|
||||
"voters": "Voters",
|
||||
@@ -79,27 +66,23 @@
|
||||
"reputation": "السمعة",
|
||||
"lastpost": "Last post",
|
||||
"firstpost": "First post",
|
||||
"about": "About",
|
||||
"read-more": "اقرأ المزيد",
|
||||
"read_more": "اقرأ المزيد",
|
||||
"more": "المزيد",
|
||||
"none": "None",
|
||||
"posted-ago-by-guest": "كتب %1 بواسطة زائر",
|
||||
"posted-ago-by": "كتب %1 بواسطة %2",
|
||||
"posted-ago": "كتب %1",
|
||||
"posted-in": "كتب في %1",
|
||||
"posted-in-by": "كتب في 1% بواسطة %2",
|
||||
"posted-in-ago": "كتب في %1 %2",
|
||||
"posted-in-ago-by": "كتب في %1 %2 من طرف %3",
|
||||
"user-posted-ago": "%1 كتب %2",
|
||||
"guest-posted-ago": "كتب زائر %1",
|
||||
"last-edited-by": "اخر تحرير بواسطة 1%",
|
||||
"edited-timestamp": "Edited %1",
|
||||
"posted_ago_by_guest": "كتب %1 بواسطة زائر",
|
||||
"posted_ago_by": "كتب %1 بواسطة %2",
|
||||
"posted_ago": "كتب %1",
|
||||
"posted_in": "كتب في %1",
|
||||
"posted_in_by": "كتب في 1% بواسطة %2",
|
||||
"posted_in_ago": "كتب في %1 %2",
|
||||
"posted_in_ago_by": "كتب في %1 %2 من طرف %3",
|
||||
"user_posted_ago": "%1 كتب %2",
|
||||
"guest_posted_ago": "كتب زائر %1",
|
||||
"last_edited_by": "اخر تحرير بواسطة 1%",
|
||||
"norecentposts": "لاوجود لمشاركات جديدة",
|
||||
"norecenttopics": "لاوجود لمواضيع جديدة",
|
||||
"recentposts": "آخر المشاركات",
|
||||
"recentips": "آخر عناوين ال IP التي سجلت الدخول",
|
||||
"moderator-tools": "أدوات المشرف",
|
||||
"status": "Status",
|
||||
"moderator_tools": "أدوات المشرف",
|
||||
"online": "المتواجدون حاليًّا",
|
||||
"away": "غير متواجد",
|
||||
"dnd": "عدم الإزعاج",
|
||||
@@ -109,20 +92,18 @@
|
||||
"language": "اللغة",
|
||||
"guest": "زائر",
|
||||
"guests": "الزوار",
|
||||
"former-user": "A Former User",
|
||||
"system-user": "System",
|
||||
"unknown-user": "Unknown user",
|
||||
"former_user": "A Former User",
|
||||
"updated.title": "تم تحديث المنتدى",
|
||||
"updated.message": "لقد تم تحديث المنتدى إلى آخر نسخة للتو. إضغط هنا لإعادة تحميل الصفحة.",
|
||||
"privacy": "الخصوصية",
|
||||
"follow": "متابعة",
|
||||
"unfollow": "إلغاء المتابعة",
|
||||
"delete-all": "حذف الكل",
|
||||
"delete_all": "حذف الكل",
|
||||
"map": "خريطة",
|
||||
"sessions": "الجلسة",
|
||||
"ip-address": "عنوان الآي بي",
|
||||
"enter-page-number": "ادخل رقم الصفحة",
|
||||
"upload-file": "ارفع ملف",
|
||||
"ip_address": "عنوان الآي بي",
|
||||
"enter_page_number": "ادخل رقم الصفحة",
|
||||
"upload_file": "ارفع ملف",
|
||||
"upload": "ارفع",
|
||||
"uploads": "Uploads",
|
||||
"allowed-file-types": "صيغ الملفات المدعومة هي 1%",
|
||||
@@ -131,13 +112,9 @@
|
||||
"play": "تشغيل",
|
||||
"cookies.message": "هذا الموقع يستخدم ملفات تعريف الارتباط لضمان حصولك على أفضل تجربة على موقعنا.",
|
||||
"cookies.accept": "فهمت الأمر!",
|
||||
"cookies.learn-more": "أعرف المزيد",
|
||||
"cookies.learn_more": "أعرف المزيد",
|
||||
"edited": "حُرِر",
|
||||
"disabled": "معطل",
|
||||
"select": "تحديد",
|
||||
"copied": "Copied",
|
||||
"user-search-prompt": "Type something here to find users...",
|
||||
"hidden": "Hidden",
|
||||
"sort": "Sort",
|
||||
"actions": "Actions"
|
||||
"user-search-prompt": "Type something here to find users..."
|
||||
}
|
||||
@@ -1,66 +1,65 @@
|
||||
{
|
||||
"all-groups": "All groups",
|
||||
"groups": "المجموعات",
|
||||
"members": "Members",
|
||||
"view-group": "معاينة المجموعة",
|
||||
"view_group": "معاينة المجموعة",
|
||||
"owner": "مالك المجموعة",
|
||||
"new-group": "أنشئ مجموعة جديدة",
|
||||
"no-groups-found": "لاوجدود لمجموعات يمكن معاينتها",
|
||||
"new_group": "أنشئ مجموعة جديدة",
|
||||
"no_groups_found": "لاوجدود لمجموعات يمكن معاينتها",
|
||||
"pending.accept": "موافق",
|
||||
"pending.reject": "رفض",
|
||||
"pending.accept-all": "قبول الكل",
|
||||
"pending.reject-all": "رفض الكل",
|
||||
"pending.accept_all": "قبول الكل",
|
||||
"pending.reject_all": "رفض الكل",
|
||||
"pending.none": "لايوجد أعضاء ينتظرون التفعيل حالياً",
|
||||
"invited.none": "لايوجد أعضاء مدعوون في حالياً",
|
||||
"invited.uninvite": "إلغ الدعوة",
|
||||
"invited.search": "ابحث عن أعضاء لدعوتهم للمجموعة",
|
||||
"invited.notification-title": "You have been invited to join <strong>%1</strong>",
|
||||
"request.notification-title": "Group Membership Request from <strong>%1</strong>",
|
||||
"request.notification-text": "<strong>%1</strong> has requested to become a member of <strong>%2</strong>",
|
||||
"invited.notification_title": "You have been invited to join <strong>%1</strong>",
|
||||
"request.notification_title": "Group Membership Request from <strong>%1</strong>",
|
||||
"request.notification_text": "<strong>%1</strong> has requested to become a member of <strong>%2</strong>",
|
||||
"cover-save": "حفظ",
|
||||
"cover-saving": "جاري الحفظ",
|
||||
"details.title": "تفاصيل المجموعة",
|
||||
"details.members": "لائحة الأعضاء",
|
||||
"details.pending": "المستخدمون في الانتظار",
|
||||
"details.invited": "اﻷعضار المدعوون",
|
||||
"details.has-no-posts": "أعضاء هذه المجموعة لم يضيفوا أية مشاركة",
|
||||
"details.latest-posts": "آخر المشاركات",
|
||||
"details.has_no_posts": "أعضاء هذه المجموعة لم يضيفوا أية مشاركة",
|
||||
"details.latest_posts": "آخر المشاركات",
|
||||
"details.private": "خاص",
|
||||
"details.disableJoinRequests": "Disable join requests",
|
||||
"details.disableLeave": "Disallow users from leaving the group",
|
||||
"details.grant": "منح/سحب المِلكية",
|
||||
"details.kick": "طرد",
|
||||
"details.kick-confirm": "Are you sure you want to remove this member from the group?",
|
||||
"details.kick_confirm": "Are you sure you want to remove this member from the group?",
|
||||
"details.add-member": "Add Member",
|
||||
"details.owner-options": "إدارة المجموعة",
|
||||
"details.group-name": "اسم المجموعة",
|
||||
"details.member-count": "عدد اﻷعضاء",
|
||||
"details.creation-date": "تاريخ الإنشاء",
|
||||
"details.owner_options": "إدارة المجموعة",
|
||||
"details.group_name": "اسم المجموعة",
|
||||
"details.member_count": "عدد اﻷعضاء",
|
||||
"details.creation_date": "تاريخ الإنشاء",
|
||||
"details.description": "الوصف",
|
||||
"details.member-post-cids": "Category IDs to display posts from",
|
||||
"details.badge-preview": "معاينة الوسام",
|
||||
"details.change-icon": "تغيير الأيقونة",
|
||||
"details.change-label-colour": "Change Label Colour",
|
||||
"details.change-text-colour": "Change Text Colour",
|
||||
"details.badge-text": "نص الوسام",
|
||||
"details.member-post-cids": "Categories to display posts from",
|
||||
"details.member-post-cids-help": "<strong>Note</strong>: Selecting no categories will assume all categories are included. Use <code>ctrl</code> and <code>shift</code> to select multiple options.",
|
||||
"details.badge_preview": "معاينة الوسام",
|
||||
"details.change_icon": "تغيير الأيقونة",
|
||||
"details.change_label_colour": "Change Label Colour",
|
||||
"details.change_text_colour": "Change Text Colour",
|
||||
"details.badge_text": "نص الوسام",
|
||||
"details.userTitleEnabled": "إظهار الوسام",
|
||||
"details.private-help": "في حالة تفعيل الخيار، الانضمام إلى المجموعة يستلزم قبول مالكها",
|
||||
"details.private_help": "في حالة تفعيل الخيار، الانضمام إلى المجموعة يستلزم قبول مالكها",
|
||||
"details.hidden": "مخفي",
|
||||
"details.hidden-help": "في حالة تفعيل الخيار، لن تظهر المجموعة للعموم والإنضمام إليها سيتلزم دعوة.",
|
||||
"details.delete-group": "حذف المجموعة",
|
||||
"details.private-system-help": "Private groups is disabled at system level, this option does not do anything",
|
||||
"details.hidden_help": "في حالة تفعيل الخيار، لن تظهر المجموعة للعموم والإنضمام إليها سيتلزم دعوة.",
|
||||
"details.delete_group": "حذف المجموعة",
|
||||
"details.private_system_help": "Private groups is disabled at system level, this option does not do anything",
|
||||
"event.updated": "تم تحديث بيانات المجموعة",
|
||||
"event.deleted": "تم حذف المجموعة %1",
|
||||
"membership.accept-invitation": "اقبل الدعوة",
|
||||
"membership.accept.notification-title": "You are now a member of <strong>%1</strong>",
|
||||
"membership.accept.notification_title": "You are now a member of <strong>%1</strong>",
|
||||
"membership.invitation-pending": "الدعوة بانتظار القبول",
|
||||
"membership.join-group": "انظم للمجموعة",
|
||||
"membership.leave-group": "غادر المجموعة",
|
||||
"membership.leave.notification-title": "<strong>%1</strong> has left group <strong>%2</strong>",
|
||||
"membership.leave.notification_title": "<strong>%1</strong> has left group <strong>%2</strong>",
|
||||
"membership.reject": "رفض",
|
||||
"new-group.group-name": "اسم المجموعة",
|
||||
"new-group.group_name": "اسم المجموعة",
|
||||
"upload-group-cover": "Upload group cover",
|
||||
"bulk-invite-instructions": "Enter a list of comma separated usernames to invite to this group",
|
||||
"bulk-invite": "Bulk Invite",
|
||||
"remove-group-cover-confirm": "Are you sure you want to remove the cover picture?"
|
||||
"remove_group_cover_confirm": "Are you sure you want to remove the cover picture?"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"username-email": "اسم المستخدم / البريد الإلكتروني",
|
||||
"username": "اسم المستخدم",
|
||||
"remember-me": "تذكرني؟",
|
||||
"forgot-password": "نسيت كلمة المرور؟",
|
||||
"alternative-logins": "تسجيلات الدخول البديلة",
|
||||
"failed-login-attempt": "تسجيل الدخول غير ناجح",
|
||||
"login-successful": "قمت بتسجيل الدخول بنجاح!",
|
||||
"dont-have-account": "لا تملك حساب؟",
|
||||
"logged-out-due-to-inactivity": "لقد تم تسجيل خروجك من لوحة تحكم بسبب عدم نشاطك",
|
||||
"caps-lock-enabled": "Caps Lock is enabled"
|
||||
"email": "البريد الإلكتروني",
|
||||
"remember_me": "تذكرني؟",
|
||||
"forgot_password": "نسيت كلمة المرور؟",
|
||||
"alternative_logins": "تسجيلات الدخول البديلة",
|
||||
"failed_login_attempt": "تسجيل الدخول غير ناجح",
|
||||
"login_successful": "قمت بتسجيل الدخول بنجاح!",
|
||||
"dont_have_account": "لا تملك حساب؟",
|
||||
"logged-out-due-to-inactivity": "لقد تم تسجيل خروجك من لوحة تحكم بسبب عدم نشاطك"
|
||||
}
|
||||
@@ -1,22 +1,13 @@
|
||||
{
|
||||
"chat.room-id": "Room %1",
|
||||
"chat.chatting-with": "Chat with",
|
||||
"chat.placeholder": "Type chat message here, drag & drop images, press enter to send",
|
||||
"chat.placeholder.mobile": "Type chat message here",
|
||||
"chat.scroll-up-alert": "Go to most recent message",
|
||||
"chat.usernames-and-x-others": "%1 & %2 others",
|
||||
"chat.chat-with-usernames": "Chat with %1",
|
||||
"chat.chat-with-usernames-and-x-others": "Chat with %1 & %2 others",
|
||||
"chat.chatting_with": "Chat with",
|
||||
"chat.placeholder": "أكتب رسالة دردشة هنا، اضغط ENTER للإرسال",
|
||||
"chat.scroll-up-alert": "You are looking at older messages, click here to go to most recent message.",
|
||||
"chat.send": "أرسل",
|
||||
"chat.no-active": "لا يوجد لديك دردشات نشطة.",
|
||||
"chat.user-typing-1": "<strong>%1</strong> is typing ...",
|
||||
"chat.user-typing-2": "<strong>%1</strong> and <strong>%2</strong> are typing ...",
|
||||
"chat.user-typing-3": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> are typing ...",
|
||||
"chat.user-typing-n": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> others are typing ...",
|
||||
"chat.user-has-messaged-you": "%1 أرسل لك رسالة.",
|
||||
"chat.replying-to": "Replying to %1",
|
||||
"chat.see-all": "All chats",
|
||||
"chat.mark-all-read": "Mark all read",
|
||||
"chat.no_active": "لا يوجد لديك دردشات نشطة.",
|
||||
"chat.user_typing": "%1 يكتب رسالة...",
|
||||
"chat.user_has_messaged_you": "%1 أرسل لك رسالة.",
|
||||
"chat.see_all": "عرض كل المحادثات",
|
||||
"chat.mark_all_read": "Mark all chats read",
|
||||
"chat.no-messages": "المرجو اختيار مرسل إليه لمعاينة تاريخ الدردشات",
|
||||
"chat.no-users-in-room": "No users in this room",
|
||||
"chat.recent-chats": "آخر الدردشات",
|
||||
@@ -27,105 +18,52 @@
|
||||
"chat.pop-out": "افتح الدردشة في نافذة خاصة",
|
||||
"chat.minimize": "Minimize",
|
||||
"chat.maximize": "تكبير",
|
||||
"chat.seven-days": "7 أيام",
|
||||
"chat.thirty-days": "30 يومًا",
|
||||
"chat.three-months": "3 أشهر",
|
||||
"chat.delete-message-confirm": "هل أنت متأكد من أنك تريد حذف هذه الرسالة؟",
|
||||
"chat.seven_days": "7 أيام",
|
||||
"chat.thirty_days": "30 يومًا",
|
||||
"chat.three_months": "3 أشهر",
|
||||
"chat.delete_message_confirm": "هل أنت متأكد من أنك تريد حذف هذه الرسالة؟",
|
||||
"chat.retrieving-users": "Retrieving users...",
|
||||
"chat.view-users-list": "View users list",
|
||||
"chat.pinned-messages": "Pinned Messages",
|
||||
"chat.no-pinned-messages": "There are no pinned messages",
|
||||
"chat.pin-message": "Pin Message",
|
||||
"chat.unpin-message": "Unpin Message",
|
||||
"chat.public-rooms": "Public Rooms (%1)",
|
||||
"chat.private-rooms": "Private Rooms (%1)",
|
||||
"chat.create-room": "Create Chat Room",
|
||||
"chat.private.option": "Private (Only visible to users added to room)",
|
||||
"chat.public.option": "Public (Visible to every user in selected groups)",
|
||||
"chat.public.groups-help": "To create a chat room that is visible to all users select registered-users from the group list.",
|
||||
"chat.manage-room": "Manage Chat Room",
|
||||
"chat.add-user": "Add User",
|
||||
"chat.notification-settings": "Notification Settings",
|
||||
"chat.default-notification-setting": "Default Notification Setting",
|
||||
"chat.notification-setting-room-default": "Room Default",
|
||||
"chat.notification-setting-none": "No notifications",
|
||||
"chat.notification-setting-at-mention-only": "@mention only",
|
||||
"chat.notification-setting-all-messages": "All messages",
|
||||
"chat.select-groups": "Select Groups",
|
||||
"chat.add-user-help": "Search for users here. When selected, the user will be added to the chat. The new user will not be able to see chat messages written before they were added to the conversation. Only room owners (<i class=\"fa fa-star text-warning\"></i>) may remove users from chat rooms.",
|
||||
"chat.confirm-chat-with-dnd-user": "This user has set their status to DnD(Do not disturb). Do you still want to chat with them?",
|
||||
"chat.room-name-optional": "Room Name (Optional)",
|
||||
"chat.rename-room": "Rename Room",
|
||||
"chat.rename-placeholder": "Enter your room name here",
|
||||
"chat.rename-help": "The room name set here will be viewable by all participants in the room.",
|
||||
"chat.leave": "Leave",
|
||||
"chat.leave-room": "Leave Room",
|
||||
"chat.leave": "Leave Chat",
|
||||
"chat.leave-prompt": "Are you sure you wish to leave this chat?",
|
||||
"chat.leave-help": "Leaving this chat will remove you from future correspondence in this chat. If you are re-added in the future, you will not see any chat history from prior to your re-joining.",
|
||||
"chat.delete": "Delete",
|
||||
"chat.delete-room": "Delete Room",
|
||||
"chat.delete-prompt": "Are you sure you wish to delete this chat room?",
|
||||
"chat.in-room": "In this room",
|
||||
"chat.kick": "Kick",
|
||||
"chat.show-ip": "Show IP",
|
||||
"chat.copy-text": "Copy Text",
|
||||
"chat.copy-link": "Copy Link",
|
||||
"chat.owner": "Room Owner",
|
||||
"chat.grant-rescind-ownership": "Grant/Rescind Ownership",
|
||||
"chat.system.user-join": "%1 has joined the room <span class=\"timeago\" title=\"%2\"></span>",
|
||||
"chat.system.user-leave": "%1 has left the room <span class=\"timeago\" title=\"%2\"></span>",
|
||||
"chat.system.room-rename": "%2 has renamed this room to \"%1\" <span class=\"timeago\" title=\"%3\"></span>",
|
||||
"chat.system.user-join": "%1 has joined the room",
|
||||
"chat.system.user-leave": "%1 has left the room",
|
||||
"chat.system.room-rename": "%2 has renamed this room: %1",
|
||||
"composer.compose": "اكتب",
|
||||
"composer.show-preview": "عرض المعاينة",
|
||||
"composer.hide-preview": "إخفاء المعاينة",
|
||||
"composer.help": "Help",
|
||||
"composer.user-said-in": "%1 كتب في %2",
|
||||
"composer.user-said": "%1 كتب:",
|
||||
"composer.show_preview": "عرض المعاينة",
|
||||
"composer.hide_preview": "إخفاء المعاينة",
|
||||
"composer.user_said_in": "%1 كتب في %2",
|
||||
"composer.user_said": "%1 كتب:",
|
||||
"composer.discard": "هل أنت متأكد أنك تريد التخلي عن التغييرات؟",
|
||||
"composer.submit-and-lock": "Submit and Lock",
|
||||
"composer.toggle-dropdown": "Toggle Dropdown",
|
||||
"composer.submit_and_lock": "Submit and Lock",
|
||||
"composer.toggle_dropdown": "Toggle Dropdown",
|
||||
"composer.uploading": "Uploading %1",
|
||||
"composer.formatting.bold": "Bold",
|
||||
"composer.formatting.italic": "Italic",
|
||||
"composer.formatting.heading": "Heading",
|
||||
"composer.formatting.heading1": "Heading 1",
|
||||
"composer.formatting.heading2": "Heading 2",
|
||||
"composer.formatting.heading3": "Heading 3",
|
||||
"composer.formatting.heading4": "Heading 4",
|
||||
"composer.formatting.heading5": "Heading 5",
|
||||
"composer.formatting.heading6": "Heading 6",
|
||||
"composer.formatting.list": "List",
|
||||
"composer.formatting.strikethrough": "Strikethrough",
|
||||
"composer.formatting.code": "Code",
|
||||
"composer.formatting.link": "Link",
|
||||
"composer.formatting.picture": "Image Link",
|
||||
"composer.formatting.picture": "Picture",
|
||||
"composer.upload-picture": "Upload Image",
|
||||
"composer.upload-file": "Upload File",
|
||||
"composer.zen-mode": "Zen Mode",
|
||||
"composer.select-category": "Select a category",
|
||||
"composer.zen_mode": "Zen Mode",
|
||||
"composer.select_category": "Select a category",
|
||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
||||
"composer.post-queue-alert": "Hello👋!<br/>This forum uses a post queue system, since you are a new user your post will be hidden until it is approved by our moderation team.",
|
||||
"composer.schedule-for": "Schedule topic for",
|
||||
"composer.schedule-date": "Date",
|
||||
"composer.schedule-time": "Time",
|
||||
"composer.cancel-scheduling": "Cancel Scheduling",
|
||||
"composer.change-schedule-date": "Change Date",
|
||||
"composer.set-schedule-date": "Set Date",
|
||||
"composer.discard-all-drafts": "Discard all drafts",
|
||||
"composer.no-drafts": "You have no drafts",
|
||||
"composer.discard-draft-confirm": "Do you want to discard this draft?",
|
||||
"bootbox.ok": "OK",
|
||||
"bootbox.cancel": "إلغاء",
|
||||
"bootbox.confirm": "تأكيد",
|
||||
"bootbox.submit": "Submit",
|
||||
"bootbox.send": "Send",
|
||||
"cover.dragging-title": "Cover Photo Positioning",
|
||||
"cover.dragging-message": "Drag the cover photo to the desired position and click \"Save\"",
|
||||
"cover.saved": "Cover photo image and position saved",
|
||||
"thumbs.modal.title": "Manage topic thumbnails",
|
||||
"thumbs.modal.no-thumbs": "No thumbnails found.",
|
||||
"thumbs.modal.resize-note": "<strong>Note</strong>: This forum is configured to resize topic thumbnails down to a maximum width of %1px",
|
||||
"thumbs.modal.add": "Add thumbnail",
|
||||
"thumbs.modal.remove": "Remove thumbnail",
|
||||
"thumbs.modal.confirm-remove": "Are you sure you want to remove this thumbnail?"
|
||||
"cover.dragging_title": "Cover Photo Positioning",
|
||||
"cover.dragging_message": "Drag the cover photo to the desired position and click \"Save\"",
|
||||
"cover.saved": "Cover photo image and position saved"
|
||||
}
|
||||
@@ -1,101 +1,70 @@
|
||||
{
|
||||
"title": "التنبيهات",
|
||||
"no-notifs": "ليس لديك أية تنبيهات جديدة",
|
||||
"see-all": "All notifications",
|
||||
"mark-all-read": "Mark all read",
|
||||
"back-to-home": "عودة إلى %1",
|
||||
"outgoing-link": "رابط خارجي",
|
||||
"outgoing-link-message": "أنت تغادر اﻻن %1",
|
||||
"continue-to": "استمر إلى %1",
|
||||
"return-to": "عودة إى %1",
|
||||
"new-notification": "لديك تنبيه جديد",
|
||||
"you-have-unread-notifications": "لديك تنبيهات غير مقروءة.",
|
||||
"no_notifs": "ليس لديك أية تنبيهات جديدة",
|
||||
"see_all": "عرض كل التنبيهات",
|
||||
"mark_all_read": "اجعل كل التنبيهات مقروءة",
|
||||
"back_to_home": "عودة إلى %1",
|
||||
"outgoing_link": "رابط خارجي",
|
||||
"outgoing_link_message": "أنت تغادر اﻻن %1",
|
||||
"continue_to": "استمر إلى %1",
|
||||
"return_to": "عودة إى %1",
|
||||
"new_notification": "لديك تنبيه جديد",
|
||||
"you_have_unread_notifications": "لديك تنبيهات غير مقروءة.",
|
||||
"all": "الكل",
|
||||
"topics": "مواضيع",
|
||||
"tags": "Tags",
|
||||
"categories": "Categories",
|
||||
"replies": "ردود",
|
||||
"chat": "محادثات",
|
||||
"group-chat": "Group Chats",
|
||||
"public-chat": "Public Chats",
|
||||
"follows": "متابعون",
|
||||
"upvote": "الموافقين",
|
||||
"awards": "Awards",
|
||||
"new-flags": "New Flags",
|
||||
"my-flags": "Flags assigned to me",
|
||||
"bans": "الحظر",
|
||||
"new-message-from": "رسالة جديدة من <strong>%1</strong>",
|
||||
"new-messages-from": "%1 new messages from <strong>%2</strong>",
|
||||
"new-message-in": "New message in <strong>%1</strong>",
|
||||
"new-messages-in": "%1 new messages in <strong>%2</strong>",
|
||||
"user-posted-in-public-room": "<strong>%1</strong> wrote in <strong class=\"text-nowrap\"><i class=\"fa %2\"></i>%3</strong>",
|
||||
"user-posted-in-public-room-dual": "<strong>%1</strong> and <strong>%2</strong> wrote in <strong class=\"text-nowrap\"><i class=\"fa %3\"></i>%4</strong>",
|
||||
"user-posted-in-public-room-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> wrote in <strong class=\"text-nowrap\"><i class=\"fa %4\"></i>%5</strong>",
|
||||
"user-posted-in-public-room-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others wrote in <strong class=\"text-nowrap\"><i class=\"fa %4\"></i>%5</strong>",
|
||||
"upvoted-your-post-in": "<strong>%1</strong> أضاف صوتًا إيجابيا إلى مشاركتك في <strong>%2</strong>.",
|
||||
"upvoted-your-post-in-dual": "<strong>%1</strong> and <strong>%2</strong> have upvoted your post in <strong>%3</strong>.",
|
||||
"upvoted-your-post-in-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> have upvoted your post in <strong>%4</strong>.",
|
||||
"upvoted-your-post-in-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others have upvoted your post in <strong>%4</strong>.",
|
||||
"moved-your-post": "<strong>%1</strong> has moved your post to <strong>%2</strong>",
|
||||
"moved-your-topic": "<strong>%1</strong> has moved <strong>%2</strong>",
|
||||
"user-flagged-post-in": "<strong>%1</strong> أشعَرَ بمشاركة مخلة في <strong>%2</strong>",
|
||||
"user-flagged-post-in-dual": "<strong>%1</strong> and <strong>%2</strong> flagged a post in <strong>%3</strong>",
|
||||
"user-flagged-post-in-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> flagged a post in <strong>%4</strong>",
|
||||
"user-flagged-post-in-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others flagged a post in <strong>%4</strong>",
|
||||
"user-flagged-user": "<strong>%1</strong> flagged a user profile (%2)",
|
||||
"user-flagged-user-dual": "<strong>%1</strong> and <strong>%2</strong> flagged a user profile (%3)",
|
||||
"user-flagged-user-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> flagged a user profile (%4)",
|
||||
"user-flagged-user-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others flagged a user profile (%4)",
|
||||
"user-posted-to": "<strong>%1</strong> أضاف ردا إلى: <strong>%2</strong>",
|
||||
"user-posted-to-dual": "<strong>%1</strong> and <strong>%2</strong> have posted replies to: <strong>%3</strong>",
|
||||
"user-posted-to-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> have posted replies to: <strong>%4</strong>",
|
||||
"user-posted-to-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others have posted replies to: <strong>%4</strong>",
|
||||
"user-posted-topic": "<strong>%1</strong> أنشأ موضوعًا جديدًا: <strong>%2</strong>",
|
||||
"user-edited-post": "<strong>%1</strong> has edited a post in <strong>%2</strong>",
|
||||
"user-posted-topic-with-tag": "<strong>%1</strong> has posted a new topic with tag <strong>%2</strong>",
|
||||
"user-posted-topic-with-tag-dual": "<strong>%1</strong> has posted a new topic with tags <strong>%2</strong> and <strong>%3</strong>",
|
||||
"user-posted-topic-with-tag-triple": "<strong>%1</strong> has posted a new topic with tags <strong>%2</strong>, <strong>%3</strong> and <strong>%4</strong>",
|
||||
"user-posted-topic-with-tag-multiple": "<strong>%1</strong> has posted a new topic with tags <strong>%2</strong>",
|
||||
"user-posted-topic-in-category": "<strong>%1</strong> has posted a new topic in <strong>%2</strong>",
|
||||
"user-started-following-you": "<strong>%1</strong> صار يتابعك.",
|
||||
"user-started-following-you-dual": "<strong>%1</strong> and <strong>%2</strong> started following you.",
|
||||
"user-started-following-you-triple": "<strong>%1</strong>, <strong>%2</strong> and <strong>%3</strong> started following you.",
|
||||
"user-started-following-you-multiple": "<strong>%1</strong>, <strong>%2</strong> and %3 others started following you.",
|
||||
"new-register": "<strong>%1</strong> sent a registration request.",
|
||||
"new-register-multiple": "There are <strong>%1</strong> registration requests awaiting review.",
|
||||
"flag-assigned-to-you": "تم تخصيص العلامة 1% لك",
|
||||
"post-awaiting-review": "Post awaiting review",
|
||||
"new_message_from": "رسالة جديدة من <strong>%1</strong>",
|
||||
"upvoted_your_post_in": "<strong>%1</strong> أضاف صوتًا إيجابيا إلى مشاركتك في <strong>%2</strong>.",
|
||||
"upvoted_your_post_in_dual": "<strong>%1</strong> and <strong>%2</strong> have upvoted your post in <strong>%3</strong>.",
|
||||
"upvoted_your_post_in_multiple": "<strong>%1</strong> and %2 others have upvoted your post in <strong>%3</strong>.",
|
||||
"moved_your_post": "<strong>%1</strong> has moved your post to <strong>%2</strong>",
|
||||
"moved_your_topic": "<strong>%1</strong> has moved <strong>%2</strong>",
|
||||
"user_flagged_post_in": "<strong>%1</strong> أشعَرَ بمشاركة مخلة في <strong>%2</strong>",
|
||||
"user_flagged_post_in_dual": "<strong>%1</strong> and <strong>%2</strong> flagged a post in <strong>%3</strong>",
|
||||
"user_flagged_post_in_multiple": "<strong>%1</strong> and %2 others flagged a post in <strong>%3</strong>",
|
||||
"user_flagged_user": "<strong>%1</strong> flagged a user profile (%2)",
|
||||
"user_flagged_user_dual": "<strong>%1</strong> and <strong>%2</strong> flagged a user profile (%3)",
|
||||
"user_flagged_user_multiple": "<strong>%1</strong> and %2 others flagged a user profile (%3)",
|
||||
"user_posted_to": "<strong>%1</strong> أضاف ردا إلى: <strong>%2</strong>",
|
||||
"user_posted_to_dual": "<strong>%1</strong> and <strong>%2</strong> have posted replies to: <strong>%3</strong>",
|
||||
"user_posted_to_multiple": "<strong>%1</strong> and %2 others have posted replies to: <strong>%3</strong>",
|
||||
"user_posted_topic": "<strong>%1</strong> أنشأ موضوعًا جديدًا: <strong>%2</strong>",
|
||||
"user_edited_post": "<strong>%1</strong> has edited a post in <strong>%2</strong>",
|
||||
"user_started_following_you": "<strong>%1</strong> صار يتابعك.",
|
||||
"user_started_following_you_dual": "<strong>%1</strong> and <strong>%2</strong> started following you.",
|
||||
"user_started_following_you_multiple": "<strong>%1</strong> and %2 others started following you.",
|
||||
"new_register": "<strong>%1</strong> sent a registration request.",
|
||||
"new_register_multiple": "There are <strong>%1</strong> registration requests awaiting review.",
|
||||
"flag_assigned_to_you": "تم تخصيص العلامة 1% لك",
|
||||
"post_awaiting_review": "Post awaiting review",
|
||||
"profile-exported": "<strong>%1</strong> profile exported, click to download",
|
||||
"posts-exported": "<strong>%1</strong> posts exported, click to download",
|
||||
"uploads-exported": "<strong>%1</strong> uploads exported, click to download",
|
||||
"users-csv-exported": "Users csv exported, click to download",
|
||||
"post-queue-accepted": "Your queued post has been accepted. Click here to see your post.",
|
||||
"post-queue-rejected": "Your queued post has been rejected.",
|
||||
"post-queue-notify": "Queued post received a notification:<br/>\"%1\"",
|
||||
"email-confirmed": "تم التحقق من عنوان البريد الإلكتروني",
|
||||
"email-confirmed-message": "شكرًا على إثبات صحة عنوان بريدك الإلكتروني. صار حسابك مفعلًا بالكامل.",
|
||||
"email-confirm-error-message": "حدث خطأ أثناء التحقق من عنوان بريدك الإلكتروني. ربما رمز التفعيل خاطئ أو انتهت صلاحيته.",
|
||||
"email-confirm-sent": "تم إرسال بريد التفعيل.",
|
||||
"none": "None",
|
||||
"notification-only": "التنبيهات فقط",
|
||||
"email-only": "البريد الالكتروني فقط",
|
||||
"notification-and-email": "التنبيهات والبريد اﻻلكتروني",
|
||||
"notificationType-upvote": "عندما يوافقك احدهم على منشورك",
|
||||
"notificationType-new-topic": "When someone you follow posts a topic",
|
||||
"notificationType-new-topic-with-tag": "When a topic is posted with a tag you follow",
|
||||
"notificationType-new-topic-in-category": "When a topic is posted in a category you are watching",
|
||||
"notificationType-new-reply": "When a new reply is posted in a topic you are watching",
|
||||
"notificationType-post-edit": "When a post is edited in a topic you are watching",
|
||||
"notificationType-follow": "When someone starts following you",
|
||||
"notificationType-new-chat": "When you receive a chat message",
|
||||
"notificationType-new-group-chat": "When you receive a group chat message",
|
||||
"notificationType-new-public-chat": "When you receive a public group chat message",
|
||||
"notificationType-group-invite": "When you receive a group invite",
|
||||
"notificationType-group-leave": "When a user leaves your group",
|
||||
"notificationType-group-request-membership": "When someone requests to join a group you own",
|
||||
"notificationType-new-register": "When someone gets added to registration queue",
|
||||
"notificationType-post-queue": "When a new post is queued",
|
||||
"notificationType-new-post-flag": "When a post is flagged",
|
||||
"notificationType-new-user-flag": "When a user is flagged",
|
||||
"notificationType-new-reward": "When you earn a new reward"
|
||||
"notification_only": "التنبيهات فقط",
|
||||
"email_only": "البريد الالكتروني فقط",
|
||||
"notification_and_email": "التنبيهات والبريد اﻻلكتروني",
|
||||
"notificationType_upvote": "عندما يوافقك احدهم على منشورك",
|
||||
"notificationType_new-topic": "When someone you follow posts a topic",
|
||||
"notificationType_new-reply": "When a new reply is posted in a topic you are watching",
|
||||
"notificationType_post-edit": "When a post is edited in a topic you are watching",
|
||||
"notificationType_follow": "When someone starts following you",
|
||||
"notificationType_new-chat": "When you receive a chat message",
|
||||
"notificationType_new-group-chat": "When you receive a group chat message",
|
||||
"notificationType_group-invite": "When you receive a group invite",
|
||||
"notificationType_group-request-membership": "When someone requests to join a group you own",
|
||||
"notificationType_new-register": "When someone gets added to registration queue",
|
||||
"notificationType_post-queue": "When a new post is queued",
|
||||
"notificationType_new-post-flag": "When a post is flagged",
|
||||
"notificationType_new-user-flag": "When a user is flagged"
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
"flagged-content": "Flagged Content",
|
||||
"ip-blacklist": "IP Blacklist",
|
||||
"post-queue": "Post Queue",
|
||||
"registration-queue": "Registration Queue",
|
||||
"users/online": "اﻷعضاء المتصلون",
|
||||
"users/latest": "أحدث اﻷعضاء",
|
||||
"users/sort-posts": "الأعضاء الأكثر نشاطاً",
|
||||
@@ -47,22 +46,19 @@
|
||||
"account/latest-posts": "Latest posts made by %1",
|
||||
"account/topics": "Topics created by %1",
|
||||
"account/groups": "%1's Groups",
|
||||
"account/watched-categories": "%1's Watched Categories",
|
||||
"account/watched-tags": "%1's Watched Tags",
|
||||
"account/watched_categories": "%1's Watched Categories",
|
||||
"account/bookmarks": "%1's Bookmarked Posts",
|
||||
"account/settings": "خيارات المستخدم",
|
||||
"account/settings-of": "Changing settings of %1",
|
||||
"account/watched": "Topics watched by %1",
|
||||
"account/ignored": "Topics ignored by %1",
|
||||
"account/upvoted": "Posts upvoted by %1",
|
||||
"account/downvoted": "Posts downvoted by %1",
|
||||
"account/best": "Best posts made by %1",
|
||||
"account/controversial": "Controversial posts made by %1",
|
||||
"account/blocks": "Blocked users for %1",
|
||||
"account/uploads": "Uploads by %1",
|
||||
"account/sessions": "Login Sessions",
|
||||
"confirm": "تم التحقق من عنوان البريد الإلكتروني",
|
||||
"maintenance.text": "%1 is currently undergoing maintenance.<br/>Please come back another time.",
|
||||
"maintenance.text": "جاري صيانة %1. المرجو العودة لاحقًا.",
|
||||
"maintenance.messageIntro": "بالإضافة إلى ذلك، قام مدبر النظام بترك هذه الرسالة:",
|
||||
"throttled.text": "%1 is currently unavailable due to excessive load. Please come back another time."
|
||||
}
|
||||
@@ -1,42 +1,11 @@
|
||||
|
||||
{
|
||||
"post-queue": "Post Queue",
|
||||
"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 <strong>disabled</strong>. To enable this feature, go to <a href=\"%1\">Settings → Post → Post Queue</a> and enable <strong>Post Queue</strong>.",
|
||||
"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.<br />If you have queued posts awaiting approval, you will be able to see them here.",
|
||||
"description": "There are no posts in the post queue. <br> To enable this feature, go to <a href=\"%1\">Settings → Post → Post Queue</a> and enable <strong>Post Queue</strong>.",
|
||||
"user": "User",
|
||||
"when": "When",
|
||||
"category": "Category",
|
||||
"title": "Title",
|
||||
"content": "Content",
|
||||
"posted": "Posted",
|
||||
"reply-to": "Reply to \"%1\"",
|
||||
"content-editable": "Click on content to edit",
|
||||
"category-editable": "Click on category to edit",
|
||||
"title-editable": "Click on title to edit",
|
||||
"reply": "Reply",
|
||||
"topic": "Topic",
|
||||
"accept": "Accept",
|
||||
"reject": "Reject",
|
||||
"remove": "Remove",
|
||||
"notify": "Notify",
|
||||
"notify-user": "Notify User",
|
||||
"confirm-reject": "Do you want to reject this post?",
|
||||
"confirm-remove": "Do you want to remove this post?",
|
||||
"bulk-actions": "Bulk Actions",
|
||||
"accept-all": "Accept All",
|
||||
"accept-selected": "Accept Selected",
|
||||
"reject-all": "Reject All",
|
||||
"reject-all-confirm": "Do you want to reject all posts?",
|
||||
"reject-selected": "Reject Selected",
|
||||
"reject-selected-confirm": "Do you want to reject %1 selected posts?",
|
||||
"remove-all": "Remove all",
|
||||
"remove-all-confirm": "Do you want to remove all posts?",
|
||||
"remove-selected": "Remove Selected",
|
||||
"remove-selected-confirm": "Do you want to remove %1 selected posts?",
|
||||
"bulk-accept-success": "%1 posts accepted",
|
||||
"bulk-reject-success": "%1 posts rejected"
|
||||
"content-editable": "You can click on individual content to edit before posting."
|
||||
}
|
||||
@@ -5,7 +5,15 @@
|
||||
"month": "شهر",
|
||||
"year": "سنة",
|
||||
"alltime": "دائمًا",
|
||||
"no-recent-topics": "لايوجد مواضيع جديدة",
|
||||
"no-popular-topics": "لا يوجد مواضيع شائعة",
|
||||
"load-new-posts": "Load new posts"
|
||||
"no_recent_topics": "لايوجد مواضيع جديدة",
|
||||
"no_popular_topics": "لا يوجد مواضيع شائعة",
|
||||
"there-is-a-new-topic": "يوجد موضوع جديد",
|
||||
"there-is-a-new-topic-and-a-new-post": "يوجد موضوع جديد و رد جديد",
|
||||
"there-is-a-new-topic-and-new-posts": "يوجد موضوع جديد و %1 ردود جديدة ",
|
||||
"there-are-new-topics": "يوجد %1 مواضيع جديدة",
|
||||
"there-are-new-topics-and-a-new-post": "يوجد %1 مواضيع جديدة و رد جديد",
|
||||
"there-are-new-topics-and-new-posts": "يوجد %1 مواضيع جديدة و %2 مشاركات جديدة",
|
||||
"there-is-a-new-post": "يوجد مشاركة جديدة",
|
||||
"there-are-new-posts": "يوجد %1 مشاركات جديدة",
|
||||
"click-here-to-reload": "إضغط هنا لإعادة التحميل"
|
||||
}
|
||||
@@ -1,33 +1,28 @@
|
||||
{
|
||||
"register": "تسجيل",
|
||||
"already-have-account": "Already have an account?",
|
||||
"cancel-registration": "إلغاء التسجيل",
|
||||
"cancel_registration": "إلغاء التسجيل",
|
||||
"help.email": "افتراضيا، سيتم إخفاء بريدك الإلكتروني من العامة.",
|
||||
"help.username-restrictions": "اسم مستخدم فريدة من نوعها بين 1% و 2% حرفا. بإمكان الآخرين مناداتك بـ @<span id='yourUsername'>اسم المستخدم</span>.",
|
||||
"help.minimum-password-length": "كلمة المرور يجب أن تتكون على الأقل من 1% أحرف/حروف",
|
||||
"email-address": "عنوان البريد الإلكتروني",
|
||||
"email-address-placeholder": "ادخل عنوان البريد الإلكتروني",
|
||||
"help.username_restrictions": "اسم مستخدم فريدة من نوعها بين 1% و 2% حرفا. بإمكان الآخرين مناداتك بـ @<span id='yourUsername'>اسم المستخدم</span>.",
|
||||
"help.minimum_password_length": "كلمة المرور يجب أن تتكون على الأقل من 1% أحرف/حروف",
|
||||
"email_address": "عنوان البريد الإلكتروني",
|
||||
"email_address_placeholder": "ادخل عنوان البريد الإلكتروني",
|
||||
"username": "اسم المستخدم",
|
||||
"username-placeholder": "أدخل اسم المستخدم",
|
||||
"username_placeholder": "أدخل اسم المستخدم",
|
||||
"password": "كلمة المرور",
|
||||
"password-placeholder": "أدخل كلمة المرور",
|
||||
"confirm-password": "تأكيد كلمة المرور",
|
||||
"confirm-password-placeholder": "تأكيد كلمة المرور",
|
||||
"register-now-button": "قم بالتسجيل الآن",
|
||||
"alternative-registration": "طريقة تسجيل بديلة",
|
||||
"terms-of-use": "شروط الاستخدام",
|
||||
"agree-to-terms-of-use": "أوافق على شروط الاستخدام",
|
||||
"terms-of-use-error": "يجب عليك الموافقة على شروط الاستخدام",
|
||||
"password_placeholder": "أدخل كلمة المرور",
|
||||
"confirm_password": "تأكيد كلمة المرور",
|
||||
"confirm_password_placeholder": "تأكيد كلمة المرور",
|
||||
"register_now_button": "قم بالتسجيل الآن",
|
||||
"alternative_registration": "طريقة تسجيل بديلة",
|
||||
"terms_of_use": "شروط الاستخدام",
|
||||
"agree_to_terms_of_use": "أوافق على شروط الاستخدام",
|
||||
"terms_of_use_error": "يجب عليك الموافقة على شروط الاستخدام",
|
||||
"registration-added-to-queue": "تمت إضافتك في قائمة الإنتضار. ستتلقى رسالة إلكترونية عند الموافقة على تسجيلك من قبل الإدارة.",
|
||||
"registration-queue-average-time": "Our average time for approving memberships is %1 hours %2 minutes.",
|
||||
"registration-queue-auto-approve-time": "Your membership to this forum will be fully activated in up to %1 hours.",
|
||||
"interstitial.intro": "We'd like some additional information in order to update your account…",
|
||||
"interstitial.intro-new": "We'd like some additional information before we can create your account…",
|
||||
"interstitial.errors-found": "Please review the entered information:",
|
||||
"gdpr-agree-data": "I consent to the collection and processing of my personal information on this website.",
|
||||
"gdpr-agree-email": "I consent to receive digest and notification emails from this website.",
|
||||
"gdpr-consent-denied": "You must give consent to this site to collect/process your information, and to send you emails.",
|
||||
"invite.error-admin-only": "Direct user registration has been disabled. Please contact an administrator for more details.",
|
||||
"invite.error-invite-only": "Direct user registration has been disabled. You must be invited by an existing user in order to access this forum.",
|
||||
"invite.error-invalid-data": "The registration data received does not correspond to our records. Please contact an administrator for more details"
|
||||
"interstitial.intro": "نحتاج إلى بعض المعلومات الإضافية قبل أن نتمكن من إنشاء حسابك.",
|
||||
"interstitial.errors-found": "تعذر علينا إتمام عملية التسجيل:",
|
||||
"gdpr_agree_data": "I consent to the collection and processing of my personal information on this website.",
|
||||
"gdpr_agree_email": "I consent to receive digest and notification emails from this website.",
|
||||
"gdpr_consent_denied": "You must give consent to this site to collect/process your information, and to send you emails."
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user