Compare commits
4 Commits
v1.19.1
...
protocol-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
494447741a | ||
|
|
7b174d25cb | ||
|
|
bbb03a08e9 | ||
|
|
b884b0be01 |
@@ -10,21 +10,13 @@ checks:
|
|||||||
threshold: 500
|
threshold: 500
|
||||||
method-lines:
|
method-lines:
|
||||||
config:
|
config:
|
||||||
threshold: 75
|
threshold: 50
|
||||||
method-complexity:
|
method-complexity:
|
||||||
config:
|
config:
|
||||||
threshold: 10
|
threshold: 10
|
||||||
similar-code:
|
similar-code:
|
||||||
config:
|
config:
|
||||||
threshold: 65
|
threshold: 65
|
||||||
plugins:
|
|
||||||
duplication:
|
|
||||||
enabled: true
|
|
||||||
config:
|
|
||||||
languages:
|
|
||||||
javascript:
|
|
||||||
mass_threshold: 110
|
|
||||||
count_threshold: 3
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
- "public/vendor/*"
|
- "public/vendor/*"
|
||||||
- "test/*"
|
- "test/*"
|
||||||
@@ -7,6 +7,7 @@ node_modules/
|
|||||||
logs/
|
logs/
|
||||||
/public/templates
|
/public/templates
|
||||||
/public/uploads
|
/public/uploads
|
||||||
|
/public/sounds
|
||||||
/public/vendor
|
/public/vendor
|
||||||
/public/src/modules/string.js
|
/public/src/modules/string.js
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
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"],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
- **NodeBB version:**
|
- **NodeBB version:**
|
||||||
- **NodeBB git hash:**
|
- **NodeBB git hash:**
|
||||||
- **NodeJS version:**
|
|
||||||
<!-- (to find your git hash, execute `git rev-parse HEAD` from the main NodeBB directory) -->
|
<!-- (to find your git hash, execute `git rev-parse HEAD` from the main NodeBB directory) -->
|
||||||
- **Installed NodeBB Plugins:**
|
- **Installed NodeBB Plugins:**
|
||||||
<!-- (to find installed plugins run ./nodebb plugins) -->
|
<!-- (to find installed plugins run ./nodebb plugins) -->
|
||||||
@@ -20,9 +19,6 @@
|
|||||||
<!--
|
<!--
|
||||||
1. First I did this...
|
1. First I did this...
|
||||||
2. Then, I clicked on this item...
|
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.
|
|
||||||
-->
|
-->
|
||||||
- **What you expected:**
|
- **What you expected:**
|
||||||
<!-- e.g. I expected *abc* to *xyz* -->
|
<!-- e.g. I expected *abc* to *xyz* -->
|
||||||
|
|||||||
9
.github/SECURITY.md
vendored
@@ -1,9 +0,0 @@
|
|||||||
# Reporting a security vulnerability
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
# 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).
|
|
||||||
6
.github/dependabot.yml
vendored
@@ -1,6 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: npm
|
|
||||||
directory: "/install"
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
51
.github/workflows/docker.yml
vendored
@@ -1,51 +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
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v3
|
|
||||||
with:
|
|
||||||
images: nodebb/docker
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=raw,value=latest
|
|
||||||
|
|
||||||
- name: Build and push Docker images
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
204
.github/workflows/test.yaml
vendored
@@ -1,204 +0,0 @@
|
|||||||
name: Lint and test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: Lint and test
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest]
|
|
||||||
node: [12, 14, 16]
|
|
||||||
database: [mongo-dev, mongo, redis, postgres]
|
|
||||||
include:
|
|
||||||
# only run coverage once
|
|
||||||
- os: ubuntu-latest
|
|
||||||
node: 14
|
|
||||||
coverage: true
|
|
||||||
# test under development once
|
|
||||||
- database: mongo-dev
|
|
||||||
test_env: development
|
|
||||||
# only run eslint once
|
|
||||||
- os: ubuntu-latest
|
|
||||||
node: 14
|
|
||||||
database: mongo-dev
|
|
||||||
lint: true
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
env:
|
|
||||||
TEST_ENV: ${{ matrix.test_env || 'production' }}
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: 'postgres:10-alpine'
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
# Set health checks to wait until postgres has started
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
|
||||||
# Maps port 5432 on service container to the host
|
|
||||||
- 5432:5432
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: 'redis:2.8.9'
|
|
||||||
# Set health checks to wait until redis has started
|
|
||||||
options: >-
|
|
||||||
--health-cmd "redis-cli ping"
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
|
||||||
# Maps port 6379 on service container to the host
|
|
||||||
- 6379:6379
|
|
||||||
|
|
||||||
mongo:
|
|
||||||
image: 'mongo:3.6'
|
|
||||||
ports:
|
|
||||||
# Maps port 27017 on service container to the host
|
|
||||||
- 27017:27017
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- run: cp install/package.json package.json
|
|
||||||
|
|
||||||
- name: Install Node
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node }}
|
|
||||||
|
|
||||||
- name: NPM Install
|
|
||||||
uses: bahmutov/npm-install@v1
|
|
||||||
with:
|
|
||||||
useLockFile: false
|
|
||||||
|
|
||||||
- name: Setup on MongoDB
|
|
||||||
if: startsWith(matrix.database, 'mongo')
|
|
||||||
env:
|
|
||||||
SETUP: >-
|
|
||||||
{
|
|
||||||
"url": "http://127.0.0.1:4567",
|
|
||||||
"secret": "abcdef",
|
|
||||||
"admin:username": "admin",
|
|
||||||
"admin:email": "test@example.org",
|
|
||||||
"admin:password": "hAN3Eg8W",
|
|
||||||
"admin:password:confirm": "hAN3Eg8W",
|
|
||||||
|
|
||||||
"database": "mongo",
|
|
||||||
"mongo:host": "127.0.0.1",
|
|
||||||
"mongo:port": 27017,
|
|
||||||
"mongo:username": "",
|
|
||||||
"mongo:password": "",
|
|
||||||
"mongo:database": "nodebb"
|
|
||||||
}
|
|
||||||
CI: >-
|
|
||||||
{
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 27017,
|
|
||||||
"database": "ci_test"
|
|
||||||
}
|
|
||||||
run: |
|
|
||||||
node app --setup="${SETUP}" --ci="${CI}"
|
|
||||||
|
|
||||||
- name: Setup on PostgreSQL
|
|
||||||
if: startsWith(matrix.database, 'postgres')
|
|
||||||
env:
|
|
||||||
SETUP: >-
|
|
||||||
{
|
|
||||||
"url": "http://127.0.0.1:4567",
|
|
||||||
"secret": "abcdef",
|
|
||||||
"admin:username": "admin",
|
|
||||||
"admin:email": "test@example.org",
|
|
||||||
"admin:password": "hAN3Eg8W",
|
|
||||||
"admin:password:confirm": "hAN3Eg8W",
|
|
||||||
|
|
||||||
"database": "postgres",
|
|
||||||
"postgres:host": "127.0.0.1",
|
|
||||||
"postgres:port": 5432,
|
|
||||||
"postgres:username": "postgres",
|
|
||||||
"postgres:password": "postgres",
|
|
||||||
"postgres:database": "nodebb"
|
|
||||||
}
|
|
||||||
CI: >-
|
|
||||||
{
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"database": "ci_test",
|
|
||||||
"port": 5432,
|
|
||||||
"username": "postgres",
|
|
||||||
"password": "postgres"
|
|
||||||
}
|
|
||||||
run: |
|
|
||||||
node -e "const { Client } = require('pg'); const c = new Client({ host: '127.0.0.1', port: 5432, user: 'postgres', password: 'postgres' }); c.connect().then(() => c.query('CREATE DATABASE nodebb')).then(() => c.query('CREATE DATABASE ci_test')).then(() => c.end())"
|
|
||||||
node app --setup="${SETUP}" --ci="${CI}"
|
|
||||||
|
|
||||||
- name: Setup on Redis
|
|
||||||
if: startsWith(matrix.database, 'redis')
|
|
||||||
env:
|
|
||||||
SETUP: >-
|
|
||||||
{
|
|
||||||
"url": "http://127.0.0.1:4567/forum",
|
|
||||||
"secret": "abcdef",
|
|
||||||
"admin:username": "admin",
|
|
||||||
"admin:email": "test@example.org",
|
|
||||||
"admin:password": "hAN3Eg8W",
|
|
||||||
"admin:password:confirm": "hAN3Eg8W",
|
|
||||||
|
|
||||||
"database": "redis",
|
|
||||||
"redis:host": "127.0.0.1",
|
|
||||||
"redis:port": 6379,
|
|
||||||
"redis:password": "",
|
|
||||||
"redis:database": 0
|
|
||||||
}
|
|
||||||
CI: >-
|
|
||||||
{
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"database": 1,
|
|
||||||
"port": 6379
|
|
||||||
}
|
|
||||||
run: |
|
|
||||||
node app --setup="${SETUP}" --ci="${CI}"
|
|
||||||
|
|
||||||
- name: Run ESLint
|
|
||||||
if: matrix.lint
|
|
||||||
run: npm run lint
|
|
||||||
|
|
||||||
- name: Node tests
|
|
||||||
run: npm test
|
|
||||||
|
|
||||||
- name: Extract coverage info
|
|
||||||
run: npm run coverage
|
|
||||||
|
|
||||||
- name: Test coverage
|
|
||||||
uses: coverallsapp/github-action@1.1.3
|
|
||||||
if: matrix.coverage
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
flag-name: ${{ matrix.os }}-node-${{ matrix.node }}-db-${{ matrix.database }}
|
|
||||||
parallel: true
|
|
||||||
|
|
||||||
finish:
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Coveralls Finished
|
|
||||||
uses: coverallsapp/github-action@1.1.3
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
parallel-finished: true
|
|
||||||
6
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
dist/
|
|
||||||
yarn.lock
|
yarn.lock
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
node_modules/
|
node_modules/
|
||||||
@@ -28,6 +27,7 @@ pidfile
|
|||||||
# templates
|
# templates
|
||||||
/public/templates
|
/public/templates
|
||||||
|
|
||||||
|
/public/sounds
|
||||||
/public/uploads
|
/public/uploads
|
||||||
/test/uploads
|
/test/uploads
|
||||||
|
|
||||||
@@ -40,7 +40,6 @@ pidfile
|
|||||||
/public/acp.min.js.map
|
/public/acp.min.js.map
|
||||||
/public/installer.css
|
/public/installer.css
|
||||||
/public/installer.min.js
|
/public/installer.min.js
|
||||||
/public/bootstrap.min.css
|
|
||||||
/public/logo.png
|
/public/logo.png
|
||||||
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||||
@@ -67,6 +66,3 @@ test/files/normalise.jpg.png
|
|||||||
test/files/normalise-resized.jpg
|
test/files/normalise-resized.jpg
|
||||||
package-lock.json
|
package-lock.json
|
||||||
/package.json
|
/package.json
|
||||||
*.mongodb
|
|
||||||
link-plugins.sh
|
|
||||||
test.sh
|
|
||||||
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
@@ -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
@@ -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
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
reporter: dot
|
|
||||||
timeout: 25000
|
|
||||||
exit: true
|
|
||||||
bail: true
|
|
||||||
47
.travis.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
services:
|
||||||
|
- mongodb
|
||||||
|
- redis-server
|
||||||
|
- postgresql
|
||||||
|
before_install:
|
||||||
|
- cp install/package.json package.json
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get --yes remove postgresql\*
|
||||||
|
- sudo apt-get install -y postgresql-12 postgresql-client-12
|
||||||
|
- sudo cp /etc/postgresql/{9.6,12}/main/pg_hba.conf
|
||||||
|
- sudo service postgresql restart 12
|
||||||
|
before_script:
|
||||||
|
- sleep 15 # wait for mongodb to be ready
|
||||||
|
- "mongo mydb_test --eval 'db.createUser({user:\"travis\", pwd: \"test\", roles: []});'"
|
||||||
|
- sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"hAN3Eg8W\\\",\\\"admin:password:confirm\\\":\\\"hAN3Eg8W\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":\\\"travis_ci_test\\\"}\"; fi"
|
||||||
|
- sh -c "if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/forum\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"hAN3Eg8W\\\",\\\"admin:password:confirm\\\":\\\"hAN3Eg8W\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":1}\"; fi"
|
||||||
|
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database nodebb;' -U postgres; psql -c 'create database travis_ci_test;' -U postgres; node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"postgres\\\",\\\"postgres:host\\\":\\\"127.0.0.1\\\",\\\"postgres:port\\\":5432,\\\"postgres:password\\\":\\\"\\\",\\\"postgres:database\\\":\\\"nodebb\\\",\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"hAN3Eg8W\\\",\\\"admin:password:confirm\\\":\\\"hAN3Eg8W\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":5432,\\\"username\\\":\\\"postgres\\\",\\\"database\\\":\\\"travis_ci_test\\\"}\"; fi"
|
||||||
|
after_success:
|
||||||
|
- "npm run coveralls"
|
||||||
|
language: node_js
|
||||||
|
sudo: false
|
||||||
|
dist: xenial
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- PGUSER=postgres
|
||||||
|
- PGPORT=5432
|
||||||
|
- CXX=g++-4.8
|
||||||
|
jobs:
|
||||||
|
- "DB=mongodb TEST_ENV=production"
|
||||||
|
- "DB=mongodb TEST_ENV=development"
|
||||||
|
- "DB=redis TEST_ENV=production"
|
||||||
|
- "DB=postgres TEST_ENV=production"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- mongodb-4.0-xenial
|
||||||
|
packages:
|
||||||
|
- g++-4.8
|
||||||
|
- mongodb-org-server
|
||||||
|
node_js:
|
||||||
|
- "12"
|
||||||
|
- "10"
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
864
.tx/config
@@ -251,106 +251,6 @@ trans.zh_CN = public/language/zh-CN/modules.json
|
|||||||
trans.zh_TW = public/language/zh-TW/modules.json
|
trans.zh_TW = public/language/zh-TW/modules.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.post-queue]
|
|
||||||
file_filter = public/language/<lang>/post-queue.json
|
|
||||||
source_file = public/language/en-GB/post-queue.json
|
|
||||||
source_lang = en_GB
|
|
||||||
trans.ar = public/language/ar/post-queue.json
|
|
||||||
trans.bg = public/language/bg/post-queue.json
|
|
||||||
trans.bn = public/language/bn/post-queue.json
|
|
||||||
trans.cs = public/language/cs/post-queue.json
|
|
||||||
trans.da = public/language/da/post-queue.json
|
|
||||||
trans.de = public/language/de/post-queue.json
|
|
||||||
trans.el = public/language/el/post-queue.json
|
|
||||||
trans.en@pirate = public/language/en-x-pirate/post-queue.json
|
|
||||||
trans.en_US = public/language/en-US/post-queue.json
|
|
||||||
trans.es = public/language/es/post-queue.json
|
|
||||||
trans.et = public/language/et/post-queue.json
|
|
||||||
trans.fa_IR = public/language/fa-IR/post-queue.json
|
|
||||||
trans.fi = public/language/fi/post-queue.json
|
|
||||||
trans.fr = public/language/fr/post-queue.json
|
|
||||||
trans.gl = public/language/gl/post-queue.json
|
|
||||||
trans.he = public/language/he/post-queue.json
|
|
||||||
trans.hr = public/language/hr/post-queue.json
|
|
||||||
trans.hu = public/language/hu/post-queue.json
|
|
||||||
trans.id = public/language/id/post-queue.json
|
|
||||||
trans.it = public/language/it/post-queue.json
|
|
||||||
trans.ja = public/language/ja/post-queue.json
|
|
||||||
trans.ko = public/language/ko/post-queue.json
|
|
||||||
trans.lt = public/language/lt/post-queue.json
|
|
||||||
trans.lv = public/language/lv/post-queue.json
|
|
||||||
trans.ms = public/language/ms/post-queue.json
|
|
||||||
trans.nb = public/language/nb/post-queue.json
|
|
||||||
trans.nl = public/language/nl/post-queue.json
|
|
||||||
trans.pl = public/language/pl/post-queue.json
|
|
||||||
trans.pt_BR = public/language/pt-BR/post-queue.json
|
|
||||||
trans.pt_PT = public/language/pt-PT/post-queue.json
|
|
||||||
trans.ro = public/language/ro/post-queue.json
|
|
||||||
trans.ru = public/language/ru/post-queue.json
|
|
||||||
trans.rw = public/language/rw/post-queue.json
|
|
||||||
trans.sc = public/language/sc/post-queue.json
|
|
||||||
trans.sk = public/language/sk/post-queue.json
|
|
||||||
trans.sl = public/language/sl/post-queue.json
|
|
||||||
trans.sr = public/language/sr/post-queue.json
|
|
||||||
trans.sv = public/language/sv/post-queue.json
|
|
||||||
trans.th = public/language/th/post-queue.json
|
|
||||||
trans.tr = public/language/tr/post-queue.json
|
|
||||||
trans.uk = public/language/uk/post-queue.json
|
|
||||||
trans.vi = public/language/vi/post-queue.json
|
|
||||||
trans.zh_CN = public/language/zh-CN/post-queue.json
|
|
||||||
trans.zh_TW = public/language/zh-TW/post-queue.json
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[nodebb.ip-blacklist]
|
|
||||||
file_filter = public/language/<lang>/ip-blacklist.json
|
|
||||||
source_file = public/language/en-GB/ip-blacklist.json
|
|
||||||
source_lang = en_GB
|
|
||||||
trans.ar = public/language/ar/ip-blacklist.json
|
|
||||||
trans.bg = public/language/bg/ip-blacklist.json
|
|
||||||
trans.bn = public/language/bn/ip-blacklist.json
|
|
||||||
trans.cs = public/language/cs/ip-blacklist.json
|
|
||||||
trans.da = public/language/da/ip-blacklist.json
|
|
||||||
trans.de = public/language/de/ip-blacklist.json
|
|
||||||
trans.el = public/language/el/ip-blacklist.json
|
|
||||||
trans.en@pirate = public/language/en-x-pirate/ip-blacklist.json
|
|
||||||
trans.en_US = public/language/en-US/ip-blacklist.json
|
|
||||||
trans.es = public/language/es/ip-blacklist.json
|
|
||||||
trans.et = public/language/et/ip-blacklist.json
|
|
||||||
trans.fa_IR = public/language/fa-IR/ip-blacklist.json
|
|
||||||
trans.fi = public/language/fi/ip-blacklist.json
|
|
||||||
trans.fr = public/language/fr/ip-blacklist.json
|
|
||||||
trans.gl = public/language/gl/ip-blacklist.json
|
|
||||||
trans.he = public/language/he/ip-blacklist.json
|
|
||||||
trans.hr = public/language/hr/ip-blacklist.json
|
|
||||||
trans.hu = public/language/hu/ip-blacklist.json
|
|
||||||
trans.id = public/language/id/ip-blacklist.json
|
|
||||||
trans.it = public/language/it/ip-blacklist.json
|
|
||||||
trans.ja = public/language/ja/ip-blacklist.json
|
|
||||||
trans.ko = public/language/ko/ip-blacklist.json
|
|
||||||
trans.lt = public/language/lt/ip-blacklist.json
|
|
||||||
trans.lv = public/language/lv/ip-blacklist.json
|
|
||||||
trans.ms = public/language/ms/ip-blacklist.json
|
|
||||||
trans.nb = public/language/nb/ip-blacklist.json
|
|
||||||
trans.nl = public/language/nl/ip-blacklist.json
|
|
||||||
trans.pl = public/language/pl/ip-blacklist.json
|
|
||||||
trans.pt_BR = public/language/pt-BR/ip-blacklist.json
|
|
||||||
trans.pt_PT = public/language/pt-PT/ip-blacklist.json
|
|
||||||
trans.ro = public/language/ro/ip-blacklist.json
|
|
||||||
trans.ru = public/language/ru/ip-blacklist.json
|
|
||||||
trans.rw = public/language/rw/ip-blacklist.json
|
|
||||||
trans.sc = public/language/sc/ip-blacklist.json
|
|
||||||
trans.sk = public/language/sk/ip-blacklist.json
|
|
||||||
trans.sl = public/language/sl/ip-blacklist.json
|
|
||||||
trans.sr = public/language/sr/ip-blacklist.json
|
|
||||||
trans.sv = public/language/sv/ip-blacklist.json
|
|
||||||
trans.th = public/language/th/ip-blacklist.json
|
|
||||||
trans.tr = public/language/tr/ip-blacklist.json
|
|
||||||
trans.uk = public/language/uk/ip-blacklist.json
|
|
||||||
trans.vi = public/language/vi/ip-blacklist.json
|
|
||||||
trans.zh_CN = public/language/zh-CN/ip-blacklist.json
|
|
||||||
trans.zh_TW = public/language/zh-TW/ip-blacklist.json
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[nodebb.register]
|
[nodebb.register]
|
||||||
file_filter = public/language/<lang>/register.json
|
file_filter = public/language/<lang>/register.json
|
||||||
source_file = public/language/en-GB/register.json
|
source_file = public/language/en-GB/register.json
|
||||||
@@ -1000,56 +900,6 @@ trans.zh_CN = public/language/zh-CN/tags.json
|
|||||||
trans.zh_TW = public/language/zh-TW/tags.json
|
trans.zh_TW = public/language/zh-TW/tags.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.top]
|
|
||||||
file_filter = public/language/<lang>/top.json
|
|
||||||
source_file = public/language/en-GB/top.json
|
|
||||||
source_lang = en_GB
|
|
||||||
trans.ar = public/language/ar/top.json
|
|
||||||
trans.bg = public/language/bg/top.json
|
|
||||||
trans.bn = public/language/bn/top.json
|
|
||||||
trans.cs = public/language/cs/top.json
|
|
||||||
trans.da = public/language/da/top.json
|
|
||||||
trans.de = public/language/de/top.json
|
|
||||||
trans.el = public/language/el/top.json
|
|
||||||
trans.en@pirate = public/language/en-x-pirate/top.json
|
|
||||||
trans.en_US = public/language/en-US/top.json
|
|
||||||
trans.es = public/language/es/top.json
|
|
||||||
trans.et = public/language/et/top.json
|
|
||||||
trans.fa_IR = public/language/fa-IR/top.json
|
|
||||||
trans.fi = public/language/fi/top.json
|
|
||||||
trans.fr = public/language/fr/top.json
|
|
||||||
trans.gl = public/language/gl/top.json
|
|
||||||
trans.he = public/language/he/top.json
|
|
||||||
trans.hr = public/language/hr/top.json
|
|
||||||
trans.hu = public/language/hu/top.json
|
|
||||||
trans.id = public/language/id/top.json
|
|
||||||
trans.it = public/language/it/top.json
|
|
||||||
trans.ja = public/language/ja/top.json
|
|
||||||
trans.ko = public/language/ko/top.json
|
|
||||||
trans.lt = public/language/lt/top.json
|
|
||||||
trans.lv = public/language/lv/top.json
|
|
||||||
trans.ms = public/language/ms/top.json
|
|
||||||
trans.nb = public/language/nb/top.json
|
|
||||||
trans.nl = public/language/nl/top.json
|
|
||||||
trans.pl = public/language/pl/top.json
|
|
||||||
trans.pt_BR = public/language/pt-BR/top.json
|
|
||||||
trans.pt_PT = public/language/pt-PT/top.json
|
|
||||||
trans.ro = public/language/ro/top.json
|
|
||||||
trans.ru = public/language/ru/top.json
|
|
||||||
trans.rw = public/language/rw/top.json
|
|
||||||
trans.sc = public/language/sc/top.json
|
|
||||||
trans.sk = public/language/sk/top.json
|
|
||||||
trans.sl = public/language/sl/top.json
|
|
||||||
trans.sr = public/language/sr/top.json
|
|
||||||
trans.sv = public/language/sv/top.json
|
|
||||||
trans.th = public/language/th/top.json
|
|
||||||
trans.tr = public/language/tr/top.json
|
|
||||||
trans.uk = public/language/uk/top.json
|
|
||||||
trans.vi = public/language/vi/top.json
|
|
||||||
trans.zh_CN = public/language/zh-CN/top.json
|
|
||||||
trans.zh_TW = public/language/zh-TW/top.json
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[nodebb.email]
|
[nodebb.email]
|
||||||
file_filter = public/language/<lang>/email.json
|
file_filter = public/language/<lang>/email.json
|
||||||
source_file = public/language/en-GB/email.json
|
source_file = public/language/en-GB/email.json
|
||||||
@@ -2000,304 +1850,304 @@ trans.zh_CN = public/language/zh-CN/admin/extend/widgets.json
|
|||||||
trans.zh_TW = public/language/zh-TW/admin/extend/widgets.json
|
trans.zh_TW = public/language/zh-TW/admin/extend/widgets.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-dashboard]
|
[nodebb.admin-general-dashboard]
|
||||||
file_filter = public/language/<lang>/admin/dashboard.json
|
file_filter = public/language/<lang>/admin/general/dashboard.json
|
||||||
source_file = public/language/en-GB/admin/dashboard.json
|
source_file = public/language/en-GB/admin/general/dashboard.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/dashboard.json
|
trans.ar = public/language/ar/admin/general/dashboard.json
|
||||||
trans.bg = public/language/bg/admin/dashboard.json
|
trans.bg = public/language/bg/admin/general/dashboard.json
|
||||||
trans.bn = public/language/bn/admin/dashboard.json
|
trans.bn = public/language/bn/admin/general/dashboard.json
|
||||||
trans.cs = public/language/cs/admin/dashboard.json
|
trans.cs = public/language/cs/admin/general/dashboard.json
|
||||||
trans.da = public/language/da/admin/dashboard.json
|
trans.da = public/language/da/admin/general/dashboard.json
|
||||||
trans.de = public/language/de/admin/dashboard.json
|
trans.de = public/language/de/admin/general/dashboard.json
|
||||||
trans.el = public/language/el/admin/dashboard.json
|
trans.el = public/language/el/admin/general/dashboard.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/dashboard.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/dashboard.json
|
||||||
trans.en_US = public/language/en-US/admin/dashboard.json
|
trans.en_US = public/language/en-US/admin/general/dashboard.json
|
||||||
trans.es = public/language/es/admin/dashboard.json
|
trans.es = public/language/es/admin/general/dashboard.json
|
||||||
trans.et = public/language/et/admin/dashboard.json
|
trans.et = public/language/et/admin/general/dashboard.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/dashboard.json
|
trans.fa_IR = public/language/fa-IR/admin/general/dashboard.json
|
||||||
trans.fi = public/language/fi/admin/dashboard.json
|
trans.fi = public/language/fi/admin/general/dashboard.json
|
||||||
trans.fr = public/language/fr/admin/dashboard.json
|
trans.fr = public/language/fr/admin/general/dashboard.json
|
||||||
trans.gl = public/language/gl/admin/dashboard.json
|
trans.gl = public/language/gl/admin/general/dashboard.json
|
||||||
trans.he = public/language/he/admin/dashboard.json
|
trans.he = public/language/he/admin/general/dashboard.json
|
||||||
trans.hr = public/language/hr/admin/dashboard.json
|
trans.hr = public/language/hr/admin/general/dashboard.json
|
||||||
trans.hu = public/language/hu/admin/dashboard.json
|
trans.hu = public/language/hu/admin/general/dashboard.json
|
||||||
trans.id = public/language/id/admin/dashboard.json
|
trans.id = public/language/id/admin/general/dashboard.json
|
||||||
trans.it = public/language/it/admin/dashboard.json
|
trans.it = public/language/it/admin/general/dashboard.json
|
||||||
trans.ja = public/language/ja/admin/dashboard.json
|
trans.ja = public/language/ja/admin/general/dashboard.json
|
||||||
trans.ko = public/language/ko/admin/dashboard.json
|
trans.ko = public/language/ko/admin/general/dashboard.json
|
||||||
trans.lt = public/language/lt/admin/dashboard.json
|
trans.lt = public/language/lt/admin/general/dashboard.json
|
||||||
trans.lv = public/language/lv/admin/dashboard.json
|
trans.lv = public/language/lv/admin/general/dashboard.json
|
||||||
trans.ms = public/language/ms/admin/dashboard.json
|
trans.ms = public/language/ms/admin/general/dashboard.json
|
||||||
trans.nb = public/language/nb/admin/dashboard.json
|
trans.nb = public/language/nb/admin/general/dashboard.json
|
||||||
trans.nl = public/language/nl/admin/dashboard.json
|
trans.nl = public/language/nl/admin/general/dashboard.json
|
||||||
trans.pl = public/language/pl/admin/dashboard.json
|
trans.pl = public/language/pl/admin/general/dashboard.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/dashboard.json
|
trans.pt_BR = public/language/pt-BR/admin/general/dashboard.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/dashboard.json
|
trans.pt_PT = public/language/pt-PT/admin/general/dashboard.json
|
||||||
trans.ro = public/language/ro/admin/dashboard.json
|
trans.ro = public/language/ro/admin/general/dashboard.json
|
||||||
trans.ru = public/language/ru/admin/dashboard.json
|
trans.ru = public/language/ru/admin/general/dashboard.json
|
||||||
trans.rw = public/language/rw/admin/dashboard.json
|
trans.rw = public/language/rw/admin/general/dashboard.json
|
||||||
trans.sc = public/language/sc/admin/dashboard.json
|
trans.sc = public/language/sc/admin/general/dashboard.json
|
||||||
trans.sk = public/language/sk/admin/dashboard.json
|
trans.sk = public/language/sk/admin/general/dashboard.json
|
||||||
trans.sl = public/language/sl/admin/dashboard.json
|
trans.sl = public/language/sl/admin/general/dashboard.json
|
||||||
trans.sr = public/language/sr/admin/dashboard.json
|
trans.sr = public/language/sr/admin/general/dashboard.json
|
||||||
trans.sv = public/language/sv/admin/dashboard.json
|
trans.sv = public/language/sv/admin/general/dashboard.json
|
||||||
trans.th = public/language/th/admin/dashboard.json
|
trans.th = public/language/th/admin/general/dashboard.json
|
||||||
trans.tr = public/language/tr/admin/dashboard.json
|
trans.tr = public/language/tr/admin/general/dashboard.json
|
||||||
trans.uk = public/language/uk/admin/dashboard.json
|
trans.uk = public/language/uk/admin/general/dashboard.json
|
||||||
trans.vi = public/language/vi/admin/dashboard.json
|
trans.vi = public/language/vi/admin/general/dashboard.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/dashboard.json
|
trans.zh_CN = public/language/zh-CN/admin/general/dashboard.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/dashboard.json
|
trans.zh_TW = public/language/zh-TW/admin/general/dashboard.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-homepage]
|
[nodebb.admin-general-homepage]
|
||||||
file_filter = public/language/<lang>/admin/settings/homepage.json
|
file_filter = public/language/<lang>/admin/general/homepage.json
|
||||||
source_file = public/language/en-GB/admin/settings/homepage.json
|
source_file = public/language/en-GB/admin/general/homepage.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/settings/homepage.json
|
trans.ar = public/language/ar/admin/general/homepage.json
|
||||||
trans.bg = public/language/bg/admin/settings/homepage.json
|
trans.bg = public/language/bg/admin/general/homepage.json
|
||||||
trans.bn = public/language/bn/admin/settings/homepage.json
|
trans.bn = public/language/bn/admin/general/homepage.json
|
||||||
trans.cs = public/language/cs/admin/settings/homepage.json
|
trans.cs = public/language/cs/admin/general/homepage.json
|
||||||
trans.da = public/language/da/admin/settings/homepage.json
|
trans.da = public/language/da/admin/general/homepage.json
|
||||||
trans.de = public/language/de/admin/settings/homepage.json
|
trans.de = public/language/de/admin/general/homepage.json
|
||||||
trans.el = public/language/el/admin/settings/homepage.json
|
trans.el = public/language/el/admin/general/homepage.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/homepage.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/homepage.json
|
||||||
trans.en_US = public/language/en-US/admin/settings/homepage.json
|
trans.en_US = public/language/en-US/admin/general/homepage.json
|
||||||
trans.es = public/language/es/admin/settings/homepage.json
|
trans.es = public/language/es/admin/general/homepage.json
|
||||||
trans.et = public/language/et/admin/settings/homepage.json
|
trans.et = public/language/et/admin/general/homepage.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/homepage.json
|
trans.fa_IR = public/language/fa-IR/admin/general/homepage.json
|
||||||
trans.fi = public/language/fi/admin/settings/homepage.json
|
trans.fi = public/language/fi/admin/general/homepage.json
|
||||||
trans.fr = public/language/fr/admin/settings/homepage.json
|
trans.fr = public/language/fr/admin/general/homepage.json
|
||||||
trans.gl = public/language/gl/admin/settings/homepage.json
|
trans.gl = public/language/gl/admin/general/homepage.json
|
||||||
trans.he = public/language/he/admin/settings/homepage.json
|
trans.he = public/language/he/admin/general/homepage.json
|
||||||
trans.hr = public/language/hr/admin/settings/homepage.json
|
trans.hr = public/language/hr/admin/general/homepage.json
|
||||||
trans.hu = public/language/hu/admin/settings/homepage.json
|
trans.hu = public/language/hu/admin/general/homepage.json
|
||||||
trans.id = public/language/id/admin/settings/homepage.json
|
trans.id = public/language/id/admin/general/homepage.json
|
||||||
trans.it = public/language/it/admin/settings/homepage.json
|
trans.it = public/language/it/admin/general/homepage.json
|
||||||
trans.ja = public/language/ja/admin/settings/homepage.json
|
trans.ja = public/language/ja/admin/general/homepage.json
|
||||||
trans.ko = public/language/ko/admin/settings/homepage.json
|
trans.ko = public/language/ko/admin/general/homepage.json
|
||||||
trans.lt = public/language/lt/admin/settings/homepage.json
|
trans.lt = public/language/lt/admin/general/homepage.json
|
||||||
trans.lv = public/language/lv/admin/settings/homepage.json
|
trans.lv = public/language/lv/admin/general/homepage.json
|
||||||
trans.ms = public/language/ms/admin/settings/homepage.json
|
trans.ms = public/language/ms/admin/general/homepage.json
|
||||||
trans.nb = public/language/nb/admin/settings/homepage.json
|
trans.nb = public/language/nb/admin/general/homepage.json
|
||||||
trans.nl = public/language/nl/admin/settings/homepage.json
|
trans.nl = public/language/nl/admin/general/homepage.json
|
||||||
trans.pl = public/language/pl/admin/settings/homepage.json
|
trans.pl = public/language/pl/admin/general/homepage.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/homepage.json
|
trans.pt_BR = public/language/pt-BR/admin/general/homepage.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/homepage.json
|
trans.pt_PT = public/language/pt-PT/admin/general/homepage.json
|
||||||
trans.ro = public/language/ro/admin/settings/homepage.json
|
trans.ro = public/language/ro/admin/general/homepage.json
|
||||||
trans.ru = public/language/ru/admin/settings/homepage.json
|
trans.ru = public/language/ru/admin/general/homepage.json
|
||||||
trans.rw = public/language/rw/admin/settings/homepage.json
|
trans.rw = public/language/rw/admin/general/homepage.json
|
||||||
trans.sc = public/language/sc/admin/settings/homepage.json
|
trans.sc = public/language/sc/admin/general/homepage.json
|
||||||
trans.sk = public/language/sk/admin/settings/homepage.json
|
trans.sk = public/language/sk/admin/general/homepage.json
|
||||||
trans.sl = public/language/sl/admin/settings/homepage.json
|
trans.sl = public/language/sl/admin/general/homepage.json
|
||||||
trans.sr = public/language/sr/admin/settings/homepage.json
|
trans.sr = public/language/sr/admin/general/homepage.json
|
||||||
trans.sv = public/language/sv/admin/settings/homepage.json
|
trans.sv = public/language/sv/admin/general/homepage.json
|
||||||
trans.th = public/language/th/admin/settings/homepage.json
|
trans.th = public/language/th/admin/general/homepage.json
|
||||||
trans.tr = public/language/tr/admin/settings/homepage.json
|
trans.tr = public/language/tr/admin/general/homepage.json
|
||||||
trans.uk = public/language/uk/admin/settings/homepage.json
|
trans.uk = public/language/uk/admin/general/homepage.json
|
||||||
trans.vi = public/language/vi/admin/settings/homepage.json
|
trans.vi = public/language/vi/admin/general/homepage.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/homepage.json
|
trans.zh_CN = public/language/zh-CN/admin/general/homepage.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/homepage.json
|
trans.zh_TW = public/language/zh-TW/admin/general/homepage.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-languages]
|
[nodebb.admin-general-languages]
|
||||||
file_filter = public/language/<lang>/admin/settings/languages.json
|
file_filter = public/language/<lang>/admin/general/languages.json
|
||||||
source_file = public/language/en-GB/admin/settings/languages.json
|
source_file = public/language/en-GB/admin/general/languages.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/settings/languages.json
|
trans.ar = public/language/ar/admin/general/languages.json
|
||||||
trans.bg = public/language/bg/admin/settings/languages.json
|
trans.bg = public/language/bg/admin/general/languages.json
|
||||||
trans.bn = public/language/bn/admin/settings/languages.json
|
trans.bn = public/language/bn/admin/general/languages.json
|
||||||
trans.cs = public/language/cs/admin/settings/languages.json
|
trans.cs = public/language/cs/admin/general/languages.json
|
||||||
trans.da = public/language/da/admin/settings/languages.json
|
trans.da = public/language/da/admin/general/languages.json
|
||||||
trans.de = public/language/de/admin/settings/languages.json
|
trans.de = public/language/de/admin/general/languages.json
|
||||||
trans.el = public/language/el/admin/settings/languages.json
|
trans.el = public/language/el/admin/general/languages.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/languages.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/languages.json
|
||||||
trans.en_US = public/language/en-US/admin/settings/languages.json
|
trans.en_US = public/language/en-US/admin/general/languages.json
|
||||||
trans.es = public/language/es/admin/settings/languages.json
|
trans.es = public/language/es/admin/general/languages.json
|
||||||
trans.et = public/language/et/admin/settings/languages.json
|
trans.et = public/language/et/admin/general/languages.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/languages.json
|
trans.fa_IR = public/language/fa-IR/admin/general/languages.json
|
||||||
trans.fi = public/language/fi/admin/settings/languages.json
|
trans.fi = public/language/fi/admin/general/languages.json
|
||||||
trans.fr = public/language/fr/admin/settings/languages.json
|
trans.fr = public/language/fr/admin/general/languages.json
|
||||||
trans.gl = public/language/gl/admin/settings/languages.json
|
trans.gl = public/language/gl/admin/general/languages.json
|
||||||
trans.he = public/language/he/admin/settings/languages.json
|
trans.he = public/language/he/admin/general/languages.json
|
||||||
trans.hr = public/language/hr/admin/settings/languages.json
|
trans.hr = public/language/hr/admin/general/languages.json
|
||||||
trans.hu = public/language/hu/admin/settings/languages.json
|
trans.hu = public/language/hu/admin/general/languages.json
|
||||||
trans.id = public/language/id/admin/settings/languages.json
|
trans.id = public/language/id/admin/general/languages.json
|
||||||
trans.it = public/language/it/admin/settings/languages.json
|
trans.it = public/language/it/admin/general/languages.json
|
||||||
trans.ja = public/language/ja/admin/settings/languages.json
|
trans.ja = public/language/ja/admin/general/languages.json
|
||||||
trans.ko = public/language/ko/admin/settings/languages.json
|
trans.ko = public/language/ko/admin/general/languages.json
|
||||||
trans.lt = public/language/lt/admin/settings/languages.json
|
trans.lt = public/language/lt/admin/general/languages.json
|
||||||
trans.lv = public/language/lv/admin/settings/languages.json
|
trans.lv = public/language/lv/admin/general/languages.json
|
||||||
trans.ms = public/language/ms/admin/settings/languages.json
|
trans.ms = public/language/ms/admin/general/languages.json
|
||||||
trans.nb = public/language/nb/admin/settings/languages.json
|
trans.nb = public/language/nb/admin/general/languages.json
|
||||||
trans.nl = public/language/nl/admin/settings/languages.json
|
trans.nl = public/language/nl/admin/general/languages.json
|
||||||
trans.pl = public/language/pl/admin/settings/languages.json
|
trans.pl = public/language/pl/admin/general/languages.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/languages.json
|
trans.pt_BR = public/language/pt-BR/admin/general/languages.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/languages.json
|
trans.pt_PT = public/language/pt-PT/admin/general/languages.json
|
||||||
trans.ro = public/language/ro/admin/settings/languages.json
|
trans.ro = public/language/ro/admin/general/languages.json
|
||||||
trans.ru = public/language/ru/admin/settings/languages.json
|
trans.ru = public/language/ru/admin/general/languages.json
|
||||||
trans.rw = public/language/rw/admin/settings/languages.json
|
trans.rw = public/language/rw/admin/general/languages.json
|
||||||
trans.sc = public/language/sc/admin/settings/languages.json
|
trans.sc = public/language/sc/admin/general/languages.json
|
||||||
trans.sk = public/language/sk/admin/settings/languages.json
|
trans.sk = public/language/sk/admin/general/languages.json
|
||||||
trans.sl = public/language/sl/admin/settings/languages.json
|
trans.sl = public/language/sl/admin/general/languages.json
|
||||||
trans.sr = public/language/sr/admin/settings/languages.json
|
trans.sr = public/language/sr/admin/general/languages.json
|
||||||
trans.sv = public/language/sv/admin/settings/languages.json
|
trans.sv = public/language/sv/admin/general/languages.json
|
||||||
trans.th = public/language/th/admin/settings/languages.json
|
trans.th = public/language/th/admin/general/languages.json
|
||||||
trans.tr = public/language/tr/admin/settings/languages.json
|
trans.tr = public/language/tr/admin/general/languages.json
|
||||||
trans.uk = public/language/uk/admin/settings/languages.json
|
trans.uk = public/language/uk/admin/general/languages.json
|
||||||
trans.vi = public/language/vi/admin/settings/languages.json
|
trans.vi = public/language/vi/admin/general/languages.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/languages.json
|
trans.zh_CN = public/language/zh-CN/admin/general/languages.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/languages.json
|
trans.zh_TW = public/language/zh-TW/admin/general/languages.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-navigation]
|
[nodebb.admin-general-navigation]
|
||||||
file_filter = public/language/<lang>/admin/settings/navigation.json
|
file_filter = public/language/<lang>/admin/general/navigation.json
|
||||||
source_file = public/language/en-GB/admin/settings/navigation.json
|
source_file = public/language/en-GB/admin/general/navigation.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/settings/navigation.json
|
trans.ar = public/language/ar/admin/general/navigation.json
|
||||||
trans.bg = public/language/bg/admin/settings/navigation.json
|
trans.bg = public/language/bg/admin/general/navigation.json
|
||||||
trans.bn = public/language/bn/admin/settings/navigation.json
|
trans.bn = public/language/bn/admin/general/navigation.json
|
||||||
trans.cs = public/language/cs/admin/settings/navigation.json
|
trans.cs = public/language/cs/admin/general/navigation.json
|
||||||
trans.da = public/language/da/admin/settings/navigation.json
|
trans.da = public/language/da/admin/general/navigation.json
|
||||||
trans.de = public/language/de/admin/settings/navigation.json
|
trans.de = public/language/de/admin/general/navigation.json
|
||||||
trans.el = public/language/el/admin/settings/navigation.json
|
trans.el = public/language/el/admin/general/navigation.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/navigation.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/navigation.json
|
||||||
trans.en_US = public/language/en-US/admin/settings/navigation.json
|
trans.en_US = public/language/en-US/admin/general/navigation.json
|
||||||
trans.es = public/language/es/admin/settings/navigation.json
|
trans.es = public/language/es/admin/general/navigation.json
|
||||||
trans.et = public/language/et/admin/settings/navigation.json
|
trans.et = public/language/et/admin/general/navigation.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/navigation.json
|
trans.fa_IR = public/language/fa-IR/admin/general/navigation.json
|
||||||
trans.fi = public/language/fi/admin/settings/navigation.json
|
trans.fi = public/language/fi/admin/general/navigation.json
|
||||||
trans.fr = public/language/fr/admin/settings/navigation.json
|
trans.fr = public/language/fr/admin/general/navigation.json
|
||||||
trans.gl = public/language/gl/admin/settings/navigation.json
|
trans.gl = public/language/gl/admin/general/navigation.json
|
||||||
trans.he = public/language/he/admin/settings/navigation.json
|
trans.he = public/language/he/admin/general/navigation.json
|
||||||
trans.hr = public/language/hr/admin/settings/navigation.json
|
trans.hr = public/language/hr/admin/general/navigation.json
|
||||||
trans.hu = public/language/hu/admin/settings/navigation.json
|
trans.hu = public/language/hu/admin/general/navigation.json
|
||||||
trans.id = public/language/id/admin/settings/navigation.json
|
trans.id = public/language/id/admin/general/navigation.json
|
||||||
trans.it = public/language/it/admin/settings/navigation.json
|
trans.it = public/language/it/admin/general/navigation.json
|
||||||
trans.ja = public/language/ja/admin/settings/navigation.json
|
trans.ja = public/language/ja/admin/general/navigation.json
|
||||||
trans.ko = public/language/ko/admin/settings/navigation.json
|
trans.ko = public/language/ko/admin/general/navigation.json
|
||||||
trans.lt = public/language/lt/admin/settings/navigation.json
|
trans.lt = public/language/lt/admin/general/navigation.json
|
||||||
trans.lv = public/language/lv/admin/settings/navigation.json
|
trans.lv = public/language/lv/admin/general/navigation.json
|
||||||
trans.ms = public/language/ms/admin/settings/navigation.json
|
trans.ms = public/language/ms/admin/general/navigation.json
|
||||||
trans.nb = public/language/nb/admin/settings/navigation.json
|
trans.nb = public/language/nb/admin/general/navigation.json
|
||||||
trans.nl = public/language/nl/admin/settings/navigation.json
|
trans.nl = public/language/nl/admin/general/navigation.json
|
||||||
trans.pl = public/language/pl/admin/settings/navigation.json
|
trans.pl = public/language/pl/admin/general/navigation.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/navigation.json
|
trans.pt_BR = public/language/pt-BR/admin/general/navigation.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/navigation.json
|
trans.pt_PT = public/language/pt-PT/admin/general/navigation.json
|
||||||
trans.ro = public/language/ro/admin/settings/navigation.json
|
trans.ro = public/language/ro/admin/general/navigation.json
|
||||||
trans.ru = public/language/ru/admin/settings/navigation.json
|
trans.ru = public/language/ru/admin/general/navigation.json
|
||||||
trans.rw = public/language/rw/admin/settings/navigation.json
|
trans.rw = public/language/rw/admin/general/navigation.json
|
||||||
trans.sc = public/language/sc/admin/settings/navigation.json
|
trans.sc = public/language/sc/admin/general/navigation.json
|
||||||
trans.sk = public/language/sk/admin/settings/navigation.json
|
trans.sk = public/language/sk/admin/general/navigation.json
|
||||||
trans.sl = public/language/sl/admin/settings/navigation.json
|
trans.sl = public/language/sl/admin/general/navigation.json
|
||||||
trans.sr = public/language/sr/admin/settings/navigation.json
|
trans.sr = public/language/sr/admin/general/navigation.json
|
||||||
trans.sv = public/language/sv/admin/settings/navigation.json
|
trans.sv = public/language/sv/admin/general/navigation.json
|
||||||
trans.th = public/language/th/admin/settings/navigation.json
|
trans.th = public/language/th/admin/general/navigation.json
|
||||||
trans.tr = public/language/tr/admin/settings/navigation.json
|
trans.tr = public/language/tr/admin/general/navigation.json
|
||||||
trans.uk = public/language/uk/admin/settings/navigation.json
|
trans.uk = public/language/uk/admin/general/navigation.json
|
||||||
trans.vi = public/language/vi/admin/settings/navigation.json
|
trans.vi = public/language/vi/admin/general/navigation.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/navigation.json
|
trans.zh_CN = public/language/zh-CN/admin/general/navigation.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/navigation.json
|
trans.zh_TW = public/language/zh-TW/admin/general/navigation.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-social]
|
[nodebb.admin-general-social]
|
||||||
file_filter = public/language/<lang>/admin/settings/social.json
|
file_filter = public/language/<lang>/admin/general/social.json
|
||||||
source_file = public/language/en-GB/admin/settings/social.json
|
source_file = public/language/en-GB/admin/general/social.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/settings/social.json
|
trans.ar = public/language/ar/admin/general/social.json
|
||||||
trans.bg = public/language/bg/admin/settings/social.json
|
trans.bg = public/language/bg/admin/general/social.json
|
||||||
trans.bn = public/language/bn/admin/settings/social.json
|
trans.bn = public/language/bn/admin/general/social.json
|
||||||
trans.cs = public/language/cs/admin/settings/social.json
|
trans.cs = public/language/cs/admin/general/social.json
|
||||||
trans.da = public/language/da/admin/settings/social.json
|
trans.da = public/language/da/admin/general/social.json
|
||||||
trans.de = public/language/de/admin/settings/social.json
|
trans.de = public/language/de/admin/general/social.json
|
||||||
trans.el = public/language/el/admin/settings/social.json
|
trans.el = public/language/el/admin/general/social.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/social.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/social.json
|
||||||
trans.en_US = public/language/en-US/admin/settings/social.json
|
trans.en_US = public/language/en-US/admin/general/social.json
|
||||||
trans.es = public/language/es/admin/settings/social.json
|
trans.es = public/language/es/admin/general/social.json
|
||||||
trans.et = public/language/et/admin/settings/social.json
|
trans.et = public/language/et/admin/general/social.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/social.json
|
trans.fa_IR = public/language/fa-IR/admin/general/social.json
|
||||||
trans.fi = public/language/fi/admin/settings/social.json
|
trans.fi = public/language/fi/admin/general/social.json
|
||||||
trans.fr = public/language/fr/admin/settings/social.json
|
trans.fr = public/language/fr/admin/general/social.json
|
||||||
trans.gl = public/language/gl/admin/settings/social.json
|
trans.gl = public/language/gl/admin/general/social.json
|
||||||
trans.he = public/language/he/admin/settings/social.json
|
trans.he = public/language/he/admin/general/social.json
|
||||||
trans.hr = public/language/hr/admin/settings/social.json
|
trans.hr = public/language/hr/admin/general/social.json
|
||||||
trans.hu = public/language/hu/admin/settings/social.json
|
trans.hu = public/language/hu/admin/general/social.json
|
||||||
trans.id = public/language/id/admin/settings/social.json
|
trans.id = public/language/id/admin/general/social.json
|
||||||
trans.it = public/language/it/admin/settings/social.json
|
trans.it = public/language/it/admin/general/social.json
|
||||||
trans.ja = public/language/ja/admin/settings/social.json
|
trans.ja = public/language/ja/admin/general/social.json
|
||||||
trans.ko = public/language/ko/admin/settings/social.json
|
trans.ko = public/language/ko/admin/general/social.json
|
||||||
trans.lt = public/language/lt/admin/settings/social.json
|
trans.lt = public/language/lt/admin/general/social.json
|
||||||
trans.lv = public/language/lv/admin/settings/social.json
|
trans.lv = public/language/lv/admin/general/social.json
|
||||||
trans.ms = public/language/ms/admin/settings/social.json
|
trans.ms = public/language/ms/admin/general/social.json
|
||||||
trans.nb = public/language/nb/admin/settings/social.json
|
trans.nb = public/language/nb/admin/general/social.json
|
||||||
trans.nl = public/language/nl/admin/settings/social.json
|
trans.nl = public/language/nl/admin/general/social.json
|
||||||
trans.pl = public/language/pl/admin/settings/social.json
|
trans.pl = public/language/pl/admin/general/social.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/social.json
|
trans.pt_BR = public/language/pt-BR/admin/general/social.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/social.json
|
trans.pt_PT = public/language/pt-PT/admin/general/social.json
|
||||||
trans.ro = public/language/ro/admin/settings/social.json
|
trans.ro = public/language/ro/admin/general/social.json
|
||||||
trans.ru = public/language/ru/admin/settings/social.json
|
trans.ru = public/language/ru/admin/general/social.json
|
||||||
trans.rw = public/language/rw/admin/settings/social.json
|
trans.rw = public/language/rw/admin/general/social.json
|
||||||
trans.sc = public/language/sc/admin/settings/social.json
|
trans.sc = public/language/sc/admin/general/social.json
|
||||||
trans.sk = public/language/sk/admin/settings/social.json
|
trans.sk = public/language/sk/admin/general/social.json
|
||||||
trans.sl = public/language/sl/admin/settings/social.json
|
trans.sl = public/language/sl/admin/general/social.json
|
||||||
trans.sr = public/language/sr/admin/settings/social.json
|
trans.sr = public/language/sr/admin/general/social.json
|
||||||
trans.sv = public/language/sv/admin/settings/social.json
|
trans.sv = public/language/sv/admin/general/social.json
|
||||||
trans.th = public/language/th/admin/settings/social.json
|
trans.th = public/language/th/admin/general/social.json
|
||||||
trans.tr = public/language/tr/admin/settings/social.json
|
trans.tr = public/language/tr/admin/general/social.json
|
||||||
trans.uk = public/language/uk/admin/settings/social.json
|
trans.uk = public/language/uk/admin/general/social.json
|
||||||
trans.vi = public/language/vi/admin/settings/social.json
|
trans.vi = public/language/vi/admin/general/social.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/social.json
|
trans.zh_CN = public/language/zh-CN/admin/general/social.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/social.json
|
trans.zh_TW = public/language/zh-TW/admin/general/social.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-sounds]
|
[nodebb.admin-general-sounds]
|
||||||
file_filter = public/language/<lang>/admin/settings/sounds.json
|
file_filter = public/language/<lang>/admin/general/sounds.json
|
||||||
source_file = public/language/en-GB/admin/settings/sounds.json
|
source_file = public/language/en-GB/admin/general/sounds.json
|
||||||
source_lang = en_GB
|
source_lang = en_GB
|
||||||
trans.ar = public/language/ar/admin/settings/sounds.json
|
trans.ar = public/language/ar/admin/general/sounds.json
|
||||||
trans.bg = public/language/bg/admin/settings/sounds.json
|
trans.bg = public/language/bg/admin/general/sounds.json
|
||||||
trans.bn = public/language/bn/admin/settings/sounds.json
|
trans.bn = public/language/bn/admin/general/sounds.json
|
||||||
trans.cs = public/language/cs/admin/settings/sounds.json
|
trans.cs = public/language/cs/admin/general/sounds.json
|
||||||
trans.da = public/language/da/admin/settings/sounds.json
|
trans.da = public/language/da/admin/general/sounds.json
|
||||||
trans.de = public/language/de/admin/settings/sounds.json
|
trans.de = public/language/de/admin/general/sounds.json
|
||||||
trans.el = public/language/el/admin/settings/sounds.json
|
trans.el = public/language/el/admin/general/sounds.json
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/sounds.json
|
trans.en@pirate = public/language/en-x-pirate/admin/general/sounds.json
|
||||||
trans.en_US = public/language/en-US/admin/settings/sounds.json
|
trans.en_US = public/language/en-US/admin/general/sounds.json
|
||||||
trans.es = public/language/es/admin/settings/sounds.json
|
trans.es = public/language/es/admin/general/sounds.json
|
||||||
trans.et = public/language/et/admin/settings/sounds.json
|
trans.et = public/language/et/admin/general/sounds.json
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/sounds.json
|
trans.fa_IR = public/language/fa-IR/admin/general/sounds.json
|
||||||
trans.fi = public/language/fi/admin/settings/sounds.json
|
trans.fi = public/language/fi/admin/general/sounds.json
|
||||||
trans.fr = public/language/fr/admin/settings/sounds.json
|
trans.fr = public/language/fr/admin/general/sounds.json
|
||||||
trans.gl = public/language/gl/admin/settings/sounds.json
|
trans.gl = public/language/gl/admin/general/sounds.json
|
||||||
trans.he = public/language/he/admin/settings/sounds.json
|
trans.he = public/language/he/admin/general/sounds.json
|
||||||
trans.hr = public/language/hr/admin/settings/sounds.json
|
trans.hr = public/language/hr/admin/general/sounds.json
|
||||||
trans.hu = public/language/hu/admin/settings/sounds.json
|
trans.hu = public/language/hu/admin/general/sounds.json
|
||||||
trans.id = public/language/id/admin/settings/sounds.json
|
trans.id = public/language/id/admin/general/sounds.json
|
||||||
trans.it = public/language/it/admin/settings/sounds.json
|
trans.it = public/language/it/admin/general/sounds.json
|
||||||
trans.ja = public/language/ja/admin/settings/sounds.json
|
trans.ja = public/language/ja/admin/general/sounds.json
|
||||||
trans.ko = public/language/ko/admin/settings/sounds.json
|
trans.ko = public/language/ko/admin/general/sounds.json
|
||||||
trans.lt = public/language/lt/admin/settings/sounds.json
|
trans.lt = public/language/lt/admin/general/sounds.json
|
||||||
trans.lv = public/language/lv/admin/settings/sounds.json
|
trans.lv = public/language/lv/admin/general/sounds.json
|
||||||
trans.ms = public/language/ms/admin/settings/sounds.json
|
trans.ms = public/language/ms/admin/general/sounds.json
|
||||||
trans.nb = public/language/nb/admin/settings/sounds.json
|
trans.nb = public/language/nb/admin/general/sounds.json
|
||||||
trans.nl = public/language/nl/admin/settings/sounds.json
|
trans.nl = public/language/nl/admin/general/sounds.json
|
||||||
trans.pl = public/language/pl/admin/settings/sounds.json
|
trans.pl = public/language/pl/admin/general/sounds.json
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/sounds.json
|
trans.pt_BR = public/language/pt-BR/admin/general/sounds.json
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/sounds.json
|
trans.pt_PT = public/language/pt-PT/admin/general/sounds.json
|
||||||
trans.ro = public/language/ro/admin/settings/sounds.json
|
trans.ro = public/language/ro/admin/general/sounds.json
|
||||||
trans.ru = public/language/ru/admin/settings/sounds.json
|
trans.ru = public/language/ru/admin/general/sounds.json
|
||||||
trans.rw = public/language/rw/admin/settings/sounds.json
|
trans.rw = public/language/rw/admin/general/sounds.json
|
||||||
trans.sc = public/language/sc/admin/settings/sounds.json
|
trans.sc = public/language/sc/admin/general/sounds.json
|
||||||
trans.sk = public/language/sk/admin/settings/sounds.json
|
trans.sk = public/language/sk/admin/general/sounds.json
|
||||||
trans.sl = public/language/sl/admin/settings/sounds.json
|
trans.sl = public/language/sl/admin/general/sounds.json
|
||||||
trans.sr = public/language/sr/admin/settings/sounds.json
|
trans.sr = public/language/sr/admin/general/sounds.json
|
||||||
trans.sv = public/language/sv/admin/settings/sounds.json
|
trans.sv = public/language/sv/admin/general/sounds.json
|
||||||
trans.th = public/language/th/admin/settings/sounds.json
|
trans.th = public/language/th/admin/general/sounds.json
|
||||||
trans.tr = public/language/tr/admin/settings/sounds.json
|
trans.tr = public/language/tr/admin/general/sounds.json
|
||||||
trans.uk = public/language/uk/admin/settings/sounds.json
|
trans.uk = public/language/uk/admin/general/sounds.json
|
||||||
trans.vi = public/language/vi/admin/settings/sounds.json
|
trans.vi = public/language/vi/admin/general/sounds.json
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/sounds.json
|
trans.zh_CN = public/language/zh-CN/admin/general/sounds.json
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/sounds.json
|
trans.zh_TW = public/language/zh-TW/admin/general/sounds.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-manage-admins-mods]
|
[nodebb.admin-manage-admins-mods]
|
||||||
@@ -2450,6 +2300,56 @@ trans.zh_CN = public/language/zh-CN/admin/manage/groups.json
|
|||||||
trans.zh_TW = public/language/zh-TW/admin/manage/groups.json
|
trans.zh_TW = public/language/zh-TW/admin/manage/groups.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
|
[nodebb.admin-manage-ip-blacklist]
|
||||||
|
file_filter = public/language/<lang>/admin/manage/ip-blacklist.json
|
||||||
|
source_file = public/language/en-GB/admin/manage/ip-blacklist.json
|
||||||
|
source_lang = en_GB
|
||||||
|
trans.ar = public/language/ar/admin/manage/ip-blacklist.json
|
||||||
|
trans.bg = public/language/bg/admin/manage/ip-blacklist.json
|
||||||
|
trans.bn = public/language/bn/admin/manage/ip-blacklist.json
|
||||||
|
trans.cs = public/language/cs/admin/manage/ip-blacklist.json
|
||||||
|
trans.da = public/language/da/admin/manage/ip-blacklist.json
|
||||||
|
trans.de = public/language/de/admin/manage/ip-blacklist.json
|
||||||
|
trans.el = public/language/el/admin/manage/ip-blacklist.json
|
||||||
|
trans.en@pirate = public/language/en-x-pirate/admin/manage/ip-blacklist.json
|
||||||
|
trans.en_US = public/language/en-US/admin/manage/ip-blacklist.json
|
||||||
|
trans.es = public/language/es/admin/manage/ip-blacklist.json
|
||||||
|
trans.et = public/language/et/admin/manage/ip-blacklist.json
|
||||||
|
trans.fa_IR = public/language/fa-IR/admin/manage/ip-blacklist.json
|
||||||
|
trans.fi = public/language/fi/admin/manage/ip-blacklist.json
|
||||||
|
trans.fr = public/language/fr/admin/manage/ip-blacklist.json
|
||||||
|
trans.gl = public/language/gl/admin/manage/ip-blacklist.json
|
||||||
|
trans.he = public/language/he/admin/manage/ip-blacklist.json
|
||||||
|
trans.hr = public/language/hr/admin/manage/ip-blacklist.json
|
||||||
|
trans.hu = public/language/hu/admin/manage/ip-blacklist.json
|
||||||
|
trans.id = public/language/id/admin/manage/ip-blacklist.json
|
||||||
|
trans.it = public/language/it/admin/manage/ip-blacklist.json
|
||||||
|
trans.ja = public/language/ja/admin/manage/ip-blacklist.json
|
||||||
|
trans.ko = public/language/ko/admin/manage/ip-blacklist.json
|
||||||
|
trans.lt = public/language/lt/admin/manage/ip-blacklist.json
|
||||||
|
trans.lv = public/language/lv/admin/manage/ip-blacklist.json
|
||||||
|
trans.ms = public/language/ms/admin/manage/ip-blacklist.json
|
||||||
|
trans.nb = public/language/nb/admin/manage/ip-blacklist.json
|
||||||
|
trans.nl = public/language/nl/admin/manage/ip-blacklist.json
|
||||||
|
trans.pl = public/language/pl/admin/manage/ip-blacklist.json
|
||||||
|
trans.pt_BR = public/language/pt-BR/admin/manage/ip-blacklist.json
|
||||||
|
trans.pt_PT = public/language/pt-PT/admin/manage/ip-blacklist.json
|
||||||
|
trans.ro = public/language/ro/admin/manage/ip-blacklist.json
|
||||||
|
trans.ru = public/language/ru/admin/manage/ip-blacklist.json
|
||||||
|
trans.rw = public/language/rw/admin/manage/ip-blacklist.json
|
||||||
|
trans.sc = public/language/sc/admin/manage/ip-blacklist.json
|
||||||
|
trans.sk = public/language/sk/admin/manage/ip-blacklist.json
|
||||||
|
trans.sl = public/language/sl/admin/manage/ip-blacklist.json
|
||||||
|
trans.sr = public/language/sr/admin/manage/ip-blacklist.json
|
||||||
|
trans.sv = public/language/sv/admin/manage/ip-blacklist.json
|
||||||
|
trans.th = public/language/th/admin/manage/ip-blacklist.json
|
||||||
|
trans.tr = public/language/tr/admin/manage/ip-blacklist.json
|
||||||
|
trans.uk = public/language/uk/admin/manage/ip-blacklist.json
|
||||||
|
trans.vi = public/language/vi/admin/manage/ip-blacklist.json
|
||||||
|
trans.zh_CN = public/language/zh-CN/admin/manage/ip-blacklist.json
|
||||||
|
trans.zh_TW = public/language/zh-TW/admin/manage/ip-blacklist.json
|
||||||
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-manage-privileges]
|
[nodebb.admin-manage-privileges]
|
||||||
file_filter = public/language/<lang>/admin/manage/privileges.json
|
file_filter = public/language/<lang>/admin/manage/privileges.json
|
||||||
source_file = public/language/en-GB/admin/manage/privileges.json
|
source_file = public/language/en-GB/admin/manage/privileges.json
|
||||||
@@ -2500,6 +2400,56 @@ trans.zh_CN = public/language/zh-CN/admin/manage/privileges.json
|
|||||||
trans.zh_TW = public/language/zh-TW/admin/manage/privileges.json
|
trans.zh_TW = public/language/zh-TW/admin/manage/privileges.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
|
[nodebb.admin-manage-post-queue]
|
||||||
|
file_filter = public/language/<lang>/admin/manage/post-queue.json
|
||||||
|
source_file = public/language/en-GB/admin/manage/post-queue.json
|
||||||
|
source_lang = en_GB
|
||||||
|
trans.ar = public/language/ar/admin/manage/post-queue.json
|
||||||
|
trans.bg = public/language/bg/admin/manage/post-queue.json
|
||||||
|
trans.bn = public/language/bn/admin/manage/post-queue.json
|
||||||
|
trans.cs = public/language/cs/admin/manage/post-queue.json
|
||||||
|
trans.da = public/language/da/admin/manage/post-queue.json
|
||||||
|
trans.de = public/language/de/admin/manage/post-queue.json
|
||||||
|
trans.el = public/language/el/admin/manage/post-queue.json
|
||||||
|
trans.en@pirate = public/language/en-x-pirate/admin/manage/post-queue.json
|
||||||
|
trans.en_US = public/language/en-US/admin/manage/post-queue.json
|
||||||
|
trans.es = public/language/es/admin/manage/post-queue.json
|
||||||
|
trans.et = public/language/et/admin/manage/post-queue.json
|
||||||
|
trans.fa_IR = public/language/fa-IR/admin/manage/post-queue.json
|
||||||
|
trans.fi = public/language/fi/admin/manage/post-queue.json
|
||||||
|
trans.fr = public/language/fr/admin/manage/post-queue.json
|
||||||
|
trans.gl = public/language/gl/admin/manage/post-queue.json
|
||||||
|
trans.he = public/language/he/admin/manage/post-queue.json
|
||||||
|
trans.hr = public/language/hr/admin/manage/post-queue.json
|
||||||
|
trans.hu = public/language/hu/admin/manage/post-queue.json
|
||||||
|
trans.id = public/language/id/admin/manage/post-queue.json
|
||||||
|
trans.it = public/language/it/admin/manage/post-queue.json
|
||||||
|
trans.ja = public/language/ja/admin/manage/post-queue.json
|
||||||
|
trans.ko = public/language/ko/admin/manage/post-queue.json
|
||||||
|
trans.lt = public/language/lt/admin/manage/post-queue.json
|
||||||
|
trans.lv = public/language/lv/admin/manage/post-queue.json
|
||||||
|
trans.ms = public/language/ms/admin/manage/post-queue.json
|
||||||
|
trans.nb = public/language/nb/admin/manage/post-queue.json
|
||||||
|
trans.nl = public/language/nl/admin/manage/post-queue.json
|
||||||
|
trans.pl = public/language/pl/admin/manage/post-queue.json
|
||||||
|
trans.pt_BR = public/language/pt-BR/admin/manage/post-queue.json
|
||||||
|
trans.pt_PT = public/language/pt-PT/admin/manage/post-queue.json
|
||||||
|
trans.ro = public/language/ro/admin/manage/post-queue.json
|
||||||
|
trans.ru = public/language/ru/admin/manage/post-queue.json
|
||||||
|
trans.rw = public/language/rw/admin/manage/post-queue.json
|
||||||
|
trans.sc = public/language/sc/admin/manage/post-queue.json
|
||||||
|
trans.sk = public/language/sk/admin/manage/post-queue.json
|
||||||
|
trans.sl = public/language/sl/admin/manage/post-queue.json
|
||||||
|
trans.sr = public/language/sr/admin/manage/post-queue.json
|
||||||
|
trans.sv = public/language/sv/admin/manage/post-queue.json
|
||||||
|
trans.th = public/language/th/admin/manage/post-queue.json
|
||||||
|
trans.tr = public/language/tr/admin/manage/post-queue.json
|
||||||
|
trans.uk = public/language/uk/admin/manage/post-queue.json
|
||||||
|
trans.vi = public/language/vi/admin/manage/post-queue.json
|
||||||
|
trans.zh_CN = public/language/zh-CN/admin/manage/post-queue.json
|
||||||
|
trans.zh_TW = public/language/zh-TW/admin/manage/post-queue.json
|
||||||
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-manage-registration]
|
[nodebb.admin-manage-registration]
|
||||||
file_filter = public/language/<lang>/admin/manage/registration.json
|
file_filter = public/language/<lang>/admin/manage/registration.json
|
||||||
source_file = public/language/en-GB/admin/manage/registration.json
|
source_file = public/language/en-GB/admin/manage/registration.json
|
||||||
@@ -3350,56 +3300,6 @@ trans.zh_CN = public/language/zh-CN/admin/settings/notifications.json
|
|||||||
trans.zh_TW = public/language/zh-TW/admin/settings/notifications.json
|
trans.zh_TW = public/language/zh-TW/admin/settings/notifications.json
|
||||||
type = KEYVALUEJSON
|
type = KEYVALUEJSON
|
||||||
|
|
||||||
[nodebb.admin-settings-api]
|
|
||||||
file_filter = public/language/<lang>/admin/settings/api.json
|
|
||||||
source_file = public/language/en-GB/admin/settings/api.json
|
|
||||||
source_lang = en_GB
|
|
||||||
trans.ar = public/language/ar/admin/settings/api.json
|
|
||||||
trans.bg = public/language/bg/admin/settings/api.json
|
|
||||||
trans.bn = public/language/bn/admin/settings/api.json
|
|
||||||
trans.cs = public/language/cs/admin/settings/api.json
|
|
||||||
trans.da = public/language/da/admin/settings/api.json
|
|
||||||
trans.de = public/language/de/admin/settings/api.json
|
|
||||||
trans.el = public/language/el/admin/settings/api.json
|
|
||||||
trans.en@pirate = public/language/en-x-pirate/admin/settings/api.json
|
|
||||||
trans.en_US = public/language/en-US/admin/settings/api.json
|
|
||||||
trans.es = public/language/es/admin/settings/api.json
|
|
||||||
trans.et = public/language/et/admin/settings/api.json
|
|
||||||
trans.fa_IR = public/language/fa-IR/admin/settings/api.json
|
|
||||||
trans.fi = public/language/fi/admin/settings/api.json
|
|
||||||
trans.fr = public/language/fr/admin/settings/api.json
|
|
||||||
trans.gl = public/language/gl/admin/settings/api.json
|
|
||||||
trans.he = public/language/he/admin/settings/api.json
|
|
||||||
trans.hr = public/language/hr/admin/settings/api.json
|
|
||||||
trans.hu = public/language/hu/admin/settings/api.json
|
|
||||||
trans.id = public/language/id/admin/settings/api.json
|
|
||||||
trans.it = public/language/it/admin/settings/api.json
|
|
||||||
trans.ja = public/language/ja/admin/settings/api.json
|
|
||||||
trans.ko = public/language/ko/admin/settings/api.json
|
|
||||||
trans.lt = public/language/lt/admin/settings/api.json
|
|
||||||
trans.lv = public/language/lv/admin/settings/api.json
|
|
||||||
trans.ms = public/language/ms/admin/settings/api.json
|
|
||||||
trans.nb = public/language/nb/admin/settings/api.json
|
|
||||||
trans.nl = public/language/nl/admin/settings/api.json
|
|
||||||
trans.pl = public/language/pl/admin/settings/api.json
|
|
||||||
trans.pt_BR = public/language/pt-BR/admin/settings/api.json
|
|
||||||
trans.pt_PT = public/language/pt-PT/admin/settings/api.json
|
|
||||||
trans.ro = public/language/ro/admin/settings/api.json
|
|
||||||
trans.ru = public/language/ru/admin/settings/api.json
|
|
||||||
trans.rw = public/language/rw/admin/settings/api.json
|
|
||||||
trans.sc = public/language/sc/admin/settings/api.json
|
|
||||||
trans.sk = public/language/sk/admin/settings/api.json
|
|
||||||
trans.sl = public/language/sl/admin/settings/api.json
|
|
||||||
trans.sr = public/language/sr/admin/settings/api.json
|
|
||||||
trans.sv = public/language/sv/admin/settings/api.json
|
|
||||||
trans.th = public/language/th/admin/settings/api.json
|
|
||||||
trans.tr = public/language/tr/admin/settings/api.json
|
|
||||||
trans.uk = public/language/uk/admin/settings/api.json
|
|
||||||
trans.vi = public/language/vi/admin/settings/api.json
|
|
||||||
trans.zh_CN = public/language/zh-CN/admin/settings/api.json
|
|
||||||
trans.zh_TW = public/language/zh-TW/admin/settings/api.json
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[nodebb.admin-settings-post]
|
[nodebb.admin-settings-post]
|
||||||
file_filter = public/language/<lang>/admin/settings/post.json
|
file_filter = public/language/<lang>/admin/settings/post.json
|
||||||
source_file = public/language/en-GB/admin/settings/post.json
|
source_file = public/language/en-GB/admin/settings/post.json
|
||||||
|
|||||||
4486
CHANGELOG.md
12
Dockerfile
@@ -1,20 +1,17 @@
|
|||||||
FROM node:lts
|
FROM node:lts
|
||||||
|
|
||||||
RUN mkdir -p /usr/src/app && \
|
RUN mkdir -p /usr/src/app
|
||||||
chown -R node:node /usr/src/app
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
ARG NODE_ENV
|
ARG NODE_ENV
|
||||||
ENV NODE_ENV $NODE_ENV
|
ENV NODE_ENV $NODE_ENV
|
||||||
|
|
||||||
COPY --chown=node:node install/package.json /usr/src/app/package.json
|
COPY install/package.json /usr/src/app/package.json
|
||||||
|
|
||||||
USER node
|
|
||||||
|
|
||||||
RUN npm install --only=prod && \
|
RUN npm install --only=prod && \
|
||||||
npm cache clean --force
|
npm cache clean --force
|
||||||
|
|
||||||
COPY --chown=node:node . /usr/src/app
|
COPY . /usr/src/app
|
||||||
|
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
daemon=false \
|
daemon=false \
|
||||||
@@ -22,4 +19,5 @@ ENV NODE_ENV=production \
|
|||||||
|
|
||||||
EXPOSE 4567
|
EXPOSE 4567
|
||||||
|
|
||||||
CMD node ./nodebb build ; node ./nodebb start
|
CMD ./nodebb start
|
||||||
|
|
||||||
|
|||||||
278
Gruntfile.js
@@ -1,34 +1,95 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
const nconf = require('nconf');
|
|
||||||
|
|
||||||
nconf.argv().env({
|
var async = require('async');
|
||||||
separator: '__',
|
var fork = require('child_process').fork;
|
||||||
});
|
var env = process.env;
|
||||||
const winston = require('winston');
|
var worker;
|
||||||
const { fork } = require('child_process');
|
var updateWorker;
|
||||||
|
var initWorker;
|
||||||
const { env } = process;
|
var incomplete = [];
|
||||||
let worker;
|
var running = 0;
|
||||||
|
|
||||||
env.NODE_ENV = env.NODE_ENV || 'development';
|
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);
|
var nconf = require('nconf');
|
||||||
|
nconf.file({
|
||||||
|
file: 'config.json',
|
||||||
|
});
|
||||||
|
|
||||||
const db = require('./src/database');
|
nconf.defaults({
|
||||||
|
base_dir: __dirname,
|
||||||
|
views_dir: './build/public/templates',
|
||||||
|
});
|
||||||
|
var winston = require('winston');
|
||||||
|
winston.configure({
|
||||||
|
transports: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
handleExceptions: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
var db = require('./src/database');
|
||||||
|
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
const args = [];
|
var args = [];
|
||||||
|
var initArgs = ['--build'];
|
||||||
if (!grunt.option('verbose')) {
|
if (!grunt.option('verbose')) {
|
||||||
args.push('--log-level=info');
|
args.push('--log-level=info');
|
||||||
nconf.set('log-level', 'info');
|
initArgs.push('--log-level=info');
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(action, filepath, target) {
|
||||||
|
var updateArgs = args.slice();
|
||||||
|
var compiling;
|
||||||
|
var time = Date.now();
|
||||||
|
|
||||||
|
if (target === 'lessUpdated_Client') {
|
||||||
|
compiling = 'clientCSS';
|
||||||
|
} else if (target === 'lessUpdated_Admin') {
|
||||||
|
compiling = 'acpCSS';
|
||||||
|
} else if (target === 'clientUpdated') {
|
||||||
|
compiling = 'js';
|
||||||
|
} else if (target === 'templatesUpdated') {
|
||||||
|
compiling = 'tpl';
|
||||||
|
} else if (target === 'langUpdated') {
|
||||||
|
compiling = 'lang';
|
||||||
|
} else if (target === 'serverUpdated') {
|
||||||
|
// Do nothing, just restart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compiling && !incomplete.includes(compiling)) {
|
||||||
|
incomplete.push(compiling);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateArgs.push('--build');
|
||||||
|
updateArgs.push(incomplete.join(','));
|
||||||
|
|
||||||
|
worker.kill();
|
||||||
|
if (updateWorker) {
|
||||||
|
updateWorker.kill('SIGKILL');
|
||||||
|
}
|
||||||
|
updateWorker = fork('app.js', updateArgs, { env: env });
|
||||||
|
running += 1;
|
||||||
|
updateWorker.on('exit', function () {
|
||||||
|
running -= 1;
|
||||||
|
if (running === 0) {
|
||||||
|
worker = fork('app.js', args, {
|
||||||
|
env: env,
|
||||||
|
});
|
||||||
|
worker.on('message', function () {
|
||||||
|
if (incomplete.length) {
|
||||||
|
incomplete = [];
|
||||||
|
|
||||||
|
if (grunt.option('verbose')) {
|
||||||
|
grunt.log.writeln('NodeBB restarted in ' + (Date.now() - time) + ' ms');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
prestart.setupWinston();
|
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
watch: {},
|
watch: {},
|
||||||
@@ -38,52 +99,52 @@ module.exports = function (grunt) {
|
|||||||
|
|
||||||
grunt.registerTask('default', ['watch']);
|
grunt.registerTask('default', ['watch']);
|
||||||
|
|
||||||
grunt.registerTask('init', async function () {
|
grunt.registerTask('init', function () {
|
||||||
const done = this.async();
|
var done = this.async();
|
||||||
let plugins = [];
|
async.waterfall([
|
||||||
if (!process.argv.includes('--core')) {
|
function (next) {
|
||||||
await db.init();
|
db.init(next);
|
||||||
plugins = await db.getSortedSetRange('plugins:active', 0, -1);
|
},
|
||||||
addBaseThemes(plugins);
|
function (next) {
|
||||||
|
db.getSortedSetRange('plugins:active', 0, -1, next);
|
||||||
|
},
|
||||||
|
function (plugins, next) {
|
||||||
|
addBaseThemes(plugins, next);
|
||||||
|
},
|
||||||
|
function (plugins, next) {
|
||||||
if (!plugins.includes('nodebb-plugin-composer-default')) {
|
if (!plugins.includes('nodebb-plugin-composer-default')) {
|
||||||
plugins.push('nodebb-plugin-composer-default');
|
plugins.push('nodebb-plugin-composer-default');
|
||||||
}
|
}
|
||||||
if (!plugins.includes('nodebb-theme-persona')) {
|
|
||||||
plugins.push('nodebb-theme-persona');
|
if (process.argv.includes('--core')) {
|
||||||
}
|
plugins = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleUpdated_Client = plugins.map(p => `node_modules/${p}/*.less`)
|
const lessUpdated_Client = plugins.map(p => 'node_modules/' + p + '/**/*.less');
|
||||||
.concat(plugins.map(p => `node_modules/${p}/*.css`))
|
const lessUpdated_Admin = plugins.map(p => 'node_modules/' + p + '/**/*.less');
|
||||||
.concat(plugins.map(p => `node_modules/${p}/+(public|static|less)/**/*.less`))
|
const clientUpdated = plugins.map(p => 'node_modules/' + p + '/**/*.js');
|
||||||
.concat(plugins.map(p => `node_modules/${p}/+(public|static)/**/*.css`));
|
const templatesUpdated = plugins.map(p => 'node_modules/' + p + '/**/*.tpl');
|
||||||
|
const langUpdated = plugins.map(p => 'node_modules/' + p + '/**/*.json');
|
||||||
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`);
|
|
||||||
|
|
||||||
grunt.config(['watch'], {
|
grunt.config(['watch'], {
|
||||||
styleUpdated_Client: {
|
lessUpdated_Client: {
|
||||||
files: [
|
files: [
|
||||||
'public/less/**/*.less',
|
'public/less/*.less',
|
||||||
...styleUpdated_Client,
|
'!public/less/admin/**/*.less',
|
||||||
|
...lessUpdated_Client,
|
||||||
|
'!node_modules/nodebb-*/node_modules/**',
|
||||||
|
'!node_modules/nodebb-*/.git/**',
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
styleUpdated_Admin: {
|
lessUpdated_Admin: {
|
||||||
files: [
|
files: [
|
||||||
'public/less/**/*.less',
|
'public/less/admin/**/*.less',
|
||||||
...styleUpdated_Admin,
|
...lessUpdated_Admin,
|
||||||
|
'!node_modules/nodebb-*/node_modules/**',
|
||||||
|
'!node_modules/nodebb-*/.git/**',
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
@@ -92,25 +153,17 @@ module.exports = function (grunt) {
|
|||||||
clientUpdated: {
|
clientUpdated: {
|
||||||
files: [
|
files: [
|
||||||
'public/src/**/*.js',
|
'public/src/**/*.js',
|
||||||
'public/vendor/**/*.js',
|
|
||||||
...clientUpdated,
|
...clientUpdated,
|
||||||
|
'!node_modules/nodebb-*/node_modules/**',
|
||||||
'node_modules/benchpressjs/build/benchpress.js',
|
'node_modules/benchpressjs/build/benchpress.js',
|
||||||
|
'!node_modules/nodebb-*/.git/**',
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
serverUpdated: {
|
serverUpdated: {
|
||||||
files: [
|
files: ['*.js', 'install/*.js', 'src/**/*.js', '!src/upgrades/**'],
|
||||||
'app.js',
|
|
||||||
'install/*.js',
|
|
||||||
'src/**/*.js',
|
|
||||||
'public/src/modules/translator.js',
|
|
||||||
'public/src/modules/helpers.js',
|
|
||||||
'public/src/utils.js',
|
|
||||||
serverUpdated,
|
|
||||||
'!src/upgrades/**',
|
|
||||||
],
|
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
},
|
},
|
||||||
@@ -119,6 +172,8 @@ module.exports = function (grunt) {
|
|||||||
files: [
|
files: [
|
||||||
'src/views/**/*.tpl',
|
'src/views/**/*.tpl',
|
||||||
...templatesUpdated,
|
...templatesUpdated,
|
||||||
|
'!node_modules/nodebb-*/node_modules/**',
|
||||||
|
'!node_modules/nodebb-*/.git/**',
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
@@ -129,88 +184,63 @@ module.exports = function (grunt) {
|
|||||||
'public/language/en-GB/*.json',
|
'public/language/en-GB/*.json',
|
||||||
'public/language/en-GB/**/*.json',
|
'public/language/en-GB/**/*.json',
|
||||||
...langUpdated,
|
...langUpdated,
|
||||||
|
'!node_modules/nodebb-*/node_modules/**',
|
||||||
|
'!node_modules/nodebb-*/.git/**',
|
||||||
|
'!node_modules/nodebb-*/plugin.json',
|
||||||
|
'!node_modules/nodebb-*/package.json',
|
||||||
|
'!node_modules/nodebb-*/theme.json',
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const build = require('./src/meta/build');
|
next();
|
||||||
if (!grunt.option('skip')) {
|
},
|
||||||
await build.build(true);
|
], done);
|
||||||
}
|
|
||||||
run();
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function run() {
|
|
||||||
if (worker) {
|
|
||||||
worker.kill();
|
|
||||||
}
|
|
||||||
|
|
||||||
const execArgv = [];
|
|
||||||
const inspect = process.argv.find(a => a.startsWith('--inspect'));
|
|
||||||
|
|
||||||
if (inspect) {
|
|
||||||
execArgv.push(inspect);
|
|
||||||
}
|
|
||||||
|
|
||||||
worker = fork('app.js', args, {
|
|
||||||
env,
|
|
||||||
execArgv,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
grunt.task.run('init');
|
grunt.task.run('init');
|
||||||
|
|
||||||
grunt.event.removeAllListeners('watch');
|
env.NODE_ENV = 'development';
|
||||||
grunt.event.on('watch', (action, filepath, target) => {
|
|
||||||
let compiling;
|
if (grunt.option('skip')) {
|
||||||
if (target === 'styleUpdated_Client') {
|
worker = fork('app.js', args, {
|
||||||
compiling = 'clientCSS';
|
env: env,
|
||||||
} else if (target === 'styleUpdated_Admin') {
|
});
|
||||||
compiling = 'acpCSS';
|
} else {
|
||||||
} else if (target === 'clientUpdated') {
|
initWorker = fork('app.js', initArgs, {
|
||||||
compiling = 'js';
|
env: env,
|
||||||
} else if (target === 'templatesUpdated') {
|
});
|
||||||
compiling = 'tpl';
|
|
||||||
} else if (target === 'langUpdated') {
|
initWorker.on('exit', function () {
|
||||||
compiling = 'lang';
|
worker = fork('app.js', args, {
|
||||||
} else if (target === 'serverUpdated') {
|
env: env,
|
||||||
// empty require cache
|
});
|
||||||
const paths = ['./src/meta/build.js', './src/meta/index.js'];
|
});
|
||||||
paths.forEach(p => delete require.cache[require.resolve(p)]);
|
|
||||||
return run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require('./src/meta/build').build([compiling], (err) => {
|
grunt.event.on('watch', update);
|
||||||
if (err) {
|
|
||||||
winston.error(err.stack);
|
|
||||||
}
|
|
||||||
if (worker) {
|
|
||||||
worker.send({ compiling: compiling });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function addBaseThemes(plugins) {
|
function addBaseThemes(plugins, callback) {
|
||||||
let themeId = plugins.find(p => p.includes('nodebb-theme-'));
|
const themeId = plugins.find(p => p.startsWith('nodebb-theme-'));
|
||||||
if (!themeId) {
|
if (!themeId) {
|
||||||
return plugins;
|
return setImmediate(callback, null, plugins);
|
||||||
}
|
}
|
||||||
let baseTheme;
|
function getBaseRecursive(themeId) {
|
||||||
do {
|
|
||||||
try {
|
try {
|
||||||
baseTheme = require(`${themeId}/theme`).baseTheme;
|
const baseTheme = require(themeId + '/theme').baseTheme;
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseTheme) {
|
if (baseTheme) {
|
||||||
plugins.push(baseTheme);
|
plugins.push(baseTheme);
|
||||||
themeId = baseTheme;
|
getBaseRecursive(baseTheme);
|
||||||
}
|
}
|
||||||
} while (baseTheme);
|
} catch (err) {
|
||||||
return plugins;
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBaseRecursive(themeId);
|
||||||
|
callback(null, plugins);
|
||||||
}
|
}
|
||||||
|
|||||||
34
README.md
@@ -1,14 +1,21 @@
|
|||||||
# 
|
# <img alt="NodeBB" src="http://i.imgur.com/mYxPPtB.png" />
|
||||||
|
|
||||||
[](https://github.com/NodeBB/NodeBB/actions/workflows/test.yaml)
|
[](https://travis-ci.org/NodeBB/NodeBB)
|
||||||
[](https://coveralls.io/github/NodeBB/NodeBB?branch=master)
|
[](https://coveralls.io/github/NodeBB/NodeBB?branch=master)
|
||||||
|
[](https://david-dm.org/nodebb/nodebb?path=install)
|
||||||
[](https://codeclimate.com/github/NodeBB/NodeBB)
|
[](https://codeclimate.com/github/NodeBB/NodeBB)
|
||||||
|
|
||||||
[**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 built on either a Redis or MongoDB 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 & Meta Discussion](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
|
## Screenshots
|
||||||
|
|
||||||
@@ -41,9 +48,8 @@ Our minimalist "Persona" theme gets you going right away, no coding experience r
|
|||||||
|
|
||||||
NodeBB requires the following software to be installed:
|
NodeBB requires the following software to be installed:
|
||||||
|
|
||||||
* A version of Node.js at least 12 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
* A version of Node.js at least 8 or greater ([installation/upgrade instructions](https://github.com/nodesource/distributions))
|
||||||
* MongoDB, version 3.6 or greater **or** Redis, version 2.8.9 or greater
|
* Redis, version 2.8.9 or greater **or** MongoDB, version 2.6 or greater
|
||||||
* If you are using [clustering](https://docs.nodebb.org/configuring/scaling/) you need Redis installed and configured.
|
|
||||||
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -70,15 +76,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).
|
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.
|
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](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")
|
|
||||||
* 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")
|
|
||||||
|
|||||||
7
app.js
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
NodeBB - A better forum platform for the modern web
|
NodeBB - A better forum platform for the modern web
|
||||||
https://github.com/NodeBB/NodeBB/
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
require('./require-main');
|
require('./require-main');
|
||||||
|
|
||||||
const nconf = require('nconf');
|
const nconf = require('nconf');
|
||||||
|
|
||||||
nconf.argv().env({
|
nconf.argv().env({
|
||||||
separator: '__',
|
separator: '__',
|
||||||
});
|
});
|
||||||
@@ -32,7 +31,6 @@ const path = require('path');
|
|||||||
|
|
||||||
const file = require('./src/file');
|
const file = require('./src/file');
|
||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
|
|
||||||
global.env = process.env.NODE_ENV || 'production';
|
global.env = process.env.NODE_ENV || 'production';
|
||||||
|
|
||||||
// Alternate configuration file support
|
// Alternate configuration file support
|
||||||
@@ -41,7 +39,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 configExists = file.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
|
||||||
|
|
||||||
const prestart = require('./src/prestart');
|
const prestart = require('./src/prestart');
|
||||||
|
|
||||||
prestart.loadConfig(configFile);
|
prestart.loadConfig(configFile);
|
||||||
prestart.setupWinston();
|
prestart.setupWinston();
|
||||||
prestart.versionCheck();
|
prestart.versionCheck();
|
||||||
@@ -49,7 +46,7 @@ winston.verbose('* using configuration stored in: %s', configFile);
|
|||||||
|
|
||||||
if (!process.send) {
|
if (!process.send) {
|
||||||
// If run using `node app`, log GNU copyright info along with server info
|
// 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 program comes with ABSOLUTELY NO WARRANTY.');
|
||||||
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||||
winston.info('');
|
winston.info('');
|
||||||
|
|||||||
@@ -1,26 +1,3 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { extends: ['@commitlint/config-angular'] };
|
||||||
extends: ['@commitlint/config-angular'],
|
|
||||||
rules: {
|
|
||||||
'header-max-length': [1, 'always', 72],
|
|
||||||
'type-enum': [
|
|
||||||
2,
|
|
||||||
'always',
|
|
||||||
[
|
|
||||||
'breaking',
|
|
||||||
'build',
|
|
||||||
'chore',
|
|
||||||
'ci',
|
|
||||||
'docs',
|
|
||||||
'feat',
|
|
||||||
'fix',
|
|
||||||
'perf',
|
|
||||||
'refactor',
|
|
||||||
'revert',
|
|
||||||
'style',
|
|
||||||
'test',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "Announcements regarding our community",
|
"description": "Announcements regarding our community",
|
||||||
"descriptionParsed": "<p>Announcements regarding our community</p>\n",
|
"descriptionParsed": "<p>Announcements regarding our community</p>\n",
|
||||||
"bgColor": "#fda34b",
|
"bgColor": "#fda34b",
|
||||||
"color": "#ffffff",
|
"color": "#fff",
|
||||||
"icon" : "fa-bullhorn",
|
"icon" : "fa-bullhorn",
|
||||||
"order": 1
|
"order": 1
|
||||||
},
|
},
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"description": "A place to talk about whatever you want",
|
"description": "A place to talk about whatever you want",
|
||||||
"descriptionParsed": "<p>A place to talk about whatever you want</p>\n",
|
"descriptionParsed": "<p>A place to talk about whatever you want</p>\n",
|
||||||
"bgColor": "#59b3d0",
|
"bgColor": "#59b3d0",
|
||||||
"color": "#ffffff",
|
"color": "#fff",
|
||||||
"icon" : "fa-comments-o",
|
"icon" : "fa-comments-o",
|
||||||
"order": 2
|
"order": 2
|
||||||
},
|
},
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"description": "Blog posts from individual members",
|
"description": "Blog posts from individual members",
|
||||||
"descriptionParsed": "<p>Blog posts from individual members</p>\n",
|
"descriptionParsed": "<p>Blog posts from individual members</p>\n",
|
||||||
"bgColor": "#86ba4b",
|
"bgColor": "#86ba4b",
|
||||||
"color": "#ffffff",
|
"color": "#fff",
|
||||||
"icon" : "fa-newspaper-o",
|
"icon" : "fa-newspaper-o",
|
||||||
"order": 4
|
"order": 4
|
||||||
},
|
},
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"description": "Got a question? Ask away!",
|
"description": "Got a question? Ask away!",
|
||||||
"descriptionParsed": "<p>Got a question? Ask away!</p>\n",
|
"descriptionParsed": "<p>Got a question? Ask away!</p>\n",
|
||||||
"bgColor": "#e95c5a",
|
"bgColor": "#e95c5a",
|
||||||
"color": "#ffffff",
|
"color": "#fff",
|
||||||
"icon" : "fa-question",
|
"icon" : "fa-question",
|
||||||
"order": 3
|
"order": 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,33 +14,27 @@
|
|||||||
"newbiePostEditDuration": 3600,
|
"newbiePostEditDuration": 3600,
|
||||||
"postDeleteDuration": 0,
|
"postDeleteDuration": 0,
|
||||||
"enablePostHistory": 1,
|
"enablePostHistory": 1,
|
||||||
"topicBacklinks": 1,
|
|
||||||
"postCacheSize": 10485760,
|
"postCacheSize": 10485760,
|
||||||
"disableChat": 0,
|
"disableChat": 0,
|
||||||
"chatEditDuration": 0,
|
"chatEditDuration": 0,
|
||||||
"chatDeleteDuration": 0,
|
"chatDeleteDuration": 0,
|
||||||
"chatMessageDelay": 200,
|
"chatMessageDelay": 200,
|
||||||
"notificationSendDelay": 60,
|
|
||||||
"newbiePostDelayThreshold": 3,
|
"newbiePostDelayThreshold": 3,
|
||||||
"postQueue": 0,
|
|
||||||
"postQueueReputationThreshold": 0,
|
"postQueueReputationThreshold": 0,
|
||||||
"groupsExemptFromPostQueue": ["administrators", "Global Moderators"],
|
"groupsExemptFromPostQueue": ["administrators", "Global Moderators"],
|
||||||
"minimumPostLength": 8,
|
"minimumPostLength": 8,
|
||||||
"maximumPostLength": 32767,
|
"maximumPostLength": 32767,
|
||||||
"systemTags": "",
|
|
||||||
"minimumTagsPerTopic": 0,
|
"minimumTagsPerTopic": 0,
|
||||||
"maximumTagsPerTopic": 5,
|
"maximumTagsPerTopic": 5,
|
||||||
"minimumTagLength": 3,
|
"minimumTagLength": 3,
|
||||||
"maximumTagLength": 15,
|
"maximumTagLength": 15,
|
||||||
"undoTimeout": 10000,
|
"allowTopicsThumbnail": 0,
|
||||||
"allowTopicsThumbnail": 1,
|
|
||||||
"registrationType": "normal",
|
"registrationType": "normal",
|
||||||
"registrationApprovalType": "normal",
|
"registrationApprovalType": "normal",
|
||||||
"allowAccountDelete": 1,
|
"allowAccountDelete": 1,
|
||||||
|
"allowFileUploads": 0,
|
||||||
"privateUploads": 0,
|
"privateUploads": 0,
|
||||||
"allowedFileExtensions": "png,jpg,bmp,txt",
|
"allowedFileExtensions": "png,jpg,bmp",
|
||||||
"uploadRateLimitThreshold": 10,
|
|
||||||
"uploadRateLimitCooldown": 60,
|
|
||||||
"allowUserHomePage": 1,
|
"allowUserHomePage": 1,
|
||||||
"allowMultipleBadges": 0,
|
"allowMultipleBadges": 0,
|
||||||
"maximumFileSize": 2048,
|
"maximumFileSize": 2048,
|
||||||
@@ -50,7 +44,7 @@
|
|||||||
"rejectImageWidth": 5000,
|
"rejectImageWidth": 5000,
|
||||||
"rejectImageHeight": 5000,
|
"rejectImageHeight": 5000,
|
||||||
"resizeImageQuality": 80,
|
"resizeImageQuality": 80,
|
||||||
"topicThumbSize": 512,
|
"topicThumbSize": 120,
|
||||||
"minimumTitleLength": 3,
|
"minimumTitleLength": 3,
|
||||||
"maximumTitleLength": 255,
|
"maximumTitleLength": 255,
|
||||||
"minimumUsernameLength": 2,
|
"minimumUsernameLength": 2,
|
||||||
@@ -66,10 +60,10 @@
|
|||||||
"profileImageDimension": 200,
|
"profileImageDimension": 200,
|
||||||
"profile:convertProfileImageToPNG": 0,
|
"profile:convertProfileImageToPNG": 0,
|
||||||
"profile:keepAllUserImages": 0,
|
"profile:keepAllUserImages": 0,
|
||||||
|
"requireEmailConfirmation": 0,
|
||||||
"gdpr_enabled": 1,
|
"gdpr_enabled": 1,
|
||||||
"allowProfileImageUploads": 1,
|
"allowProfileImageUploads": 1,
|
||||||
"teaserPost": "last-reply",
|
"teaserPost": "last-reply",
|
||||||
"showPostPreviewsOnHover": 1,
|
|
||||||
"allowPrivateGroups": 1,
|
"allowPrivateGroups": 1,
|
||||||
"unreadCutoff": 2,
|
"unreadCutoff": 2,
|
||||||
"bookmarkThreshold": 5,
|
"bookmarkThreshold": 5,
|
||||||
@@ -77,8 +71,6 @@
|
|||||||
"reputation:disabled": 0,
|
"reputation:disabled": 0,
|
||||||
"downvote:disabled": 0,
|
"downvote:disabled": 0,
|
||||||
"disableSignatures": 0,
|
"disableSignatures": 0,
|
||||||
"downvotesPerDay": 10,
|
|
||||||
"downvotesPerUserPerDay": 3,
|
|
||||||
"min:rep:downvote": 0,
|
"min:rep:downvote": 0,
|
||||||
"min:rep:flag": 0,
|
"min:rep:flag": 0,
|
||||||
"min:rep:profile-picture": 0,
|
"min:rep:profile-picture": 0,
|
||||||
@@ -86,17 +78,12 @@
|
|||||||
"min:rep:website": 0,
|
"min:rep:website": 0,
|
||||||
"min:rep:aboutme": 0,
|
"min:rep:aboutme": 0,
|
||||||
"min:rep:signature": 0,
|
"min:rep:signature": 0,
|
||||||
"flags:limitPerTarget": 0,
|
|
||||||
"notificationType_upvote": "notification",
|
"notificationType_upvote": "notification",
|
||||||
"notificationType_new-topic": "notification",
|
"notificationType_new-topic": "notification",
|
||||||
"notificationType_new-reply": "notification",
|
"notificationType_new-reply": "notification",
|
||||||
"notificationType_post-edit": "notification",
|
|
||||||
"notificationType_follow": "notification",
|
"notificationType_follow": "notification",
|
||||||
"notificationType_new-chat": "notification",
|
"notificationType_new-chat": "notification",
|
||||||
"notificationType_new-group-chat": "notification",
|
|
||||||
"notificationType_group-invite": "notification",
|
"notificationType_group-invite": "notification",
|
||||||
"notificationType_group-leave": "notification",
|
|
||||||
"notificationType_group-request-membership": "notification",
|
|
||||||
"notificationType_mention": "notification",
|
"notificationType_mention": "notification",
|
||||||
"notificationType_new-register": "notification",
|
"notificationType_new-register": "notification",
|
||||||
"notificationType_post-queue": "notification",
|
"notificationType_post-queue": "notification",
|
||||||
@@ -107,16 +94,11 @@
|
|||||||
"maxPostsPerPage": 20,
|
"maxPostsPerPage": 20,
|
||||||
"topicsPerPage": 20,
|
"topicsPerPage": 20,
|
||||||
"postsPerPage": 20,
|
"postsPerPage": 20,
|
||||||
"categoriesPerPage": 50,
|
|
||||||
"userSearchResultsPerPage": 50,
|
"userSearchResultsPerPage": 50,
|
||||||
"searchDefaultSortBy": "relevance",
|
|
||||||
"searchDefaultIn": "titlesposts",
|
|
||||||
"searchDefaultInQuick": "titles",
|
|
||||||
"maximumGroupNameLength": 255,
|
"maximumGroupNameLength": 255,
|
||||||
"maximumGroupTitleLength": 40,
|
"maximumGroupTitleLength": 40,
|
||||||
"preventTopicDeleteAfterReplies": 0,
|
"preventTopicDeleteAfterReplies": 0,
|
||||||
"feeds:disableSitemap": 0,
|
"feeds:disableSitemap": 0,
|
||||||
"feeds:disableRSS": 0,
|
|
||||||
"sitemapTopics": 500,
|
"sitemapTopics": 500,
|
||||||
"maintenanceMode": 0,
|
"maintenanceMode": 0,
|
||||||
"maintenanceModeStatus": 503,
|
"maintenanceModeStatus": 503,
|
||||||
@@ -124,26 +106,15 @@
|
|||||||
"maximumInvites": 0,
|
"maximumInvites": 0,
|
||||||
"username:disableEdit": 0,
|
"username:disableEdit": 0,
|
||||||
"email:disableEdit": 0,
|
"email:disableEdit": 0,
|
||||||
"email:smtpTransport:pool": 0,
|
"email:sendmail:rateLimit": 2,
|
||||||
|
"email:sendmail:rateDelta": 1000,
|
||||||
"hideFullname": 0,
|
"hideFullname": 0,
|
||||||
"hideEmail": 0,
|
|
||||||
"showFullnameAsDisplayName": 0,
|
|
||||||
"allowGuestHandles": 0,
|
"allowGuestHandles": 0,
|
||||||
"guestsIncrementTopicViews": 1,
|
|
||||||
"allowGuestReplyNotifications": 1,
|
|
||||||
"incrementTopicViewsInterval": 60,
|
|
||||||
"recentMaxTopics": 200,
|
|
||||||
"disableRecentCategoryFilter": 0,
|
"disableRecentCategoryFilter": 0,
|
||||||
"maximumRelatedTopics": 0,
|
"maximumRelatedTopics": 0,
|
||||||
"disableEmailSubscriptions": 0,
|
"disableEmailSubscriptions": 0,
|
||||||
"emailConfirmInterval": 10,
|
"emailConfirmInterval": 10,
|
||||||
"removeEmailNotificationImages": 0,
|
|
||||||
"sendValidationEmail": 1,
|
|
||||||
"includeUnverifiedEmails": 0,
|
|
||||||
"emailPrompt": 1,
|
|
||||||
"requireEmailAddress": 0,
|
|
||||||
"inviteExpiration": 7,
|
"inviteExpiration": 7,
|
||||||
"dailyDigestFreq": "off",
|
|
||||||
"digestHour": 17,
|
"digestHour": 17,
|
||||||
"passwordExpiryDays": 0,
|
"passwordExpiryDays": 0,
|
||||||
"hsts-maxage": 31536000,
|
"hsts-maxage": 31536000,
|
||||||
@@ -157,14 +128,5 @@
|
|||||||
"timeagoCutoff": 30,
|
"timeagoCutoff": 30,
|
||||||
"necroThreshold": 7,
|
"necroThreshold": 7,
|
||||||
"categoryWatchState": "watching",
|
"categoryWatchState": "watching",
|
||||||
"submitPluginUsage": 1,
|
"submitPluginUsage": 1
|
||||||
"showAverageApprovalTime": 1,
|
|
||||||
"autoApproveTime": 0,
|
|
||||||
"maxUserSessions": 10,
|
|
||||||
"useCompression": 0,
|
|
||||||
"updateUrlWithPostIndex": 1,
|
|
||||||
"composer:showHelpTab": 1,
|
|
||||||
"composer:allowPluginHelp": 1,
|
|
||||||
"maxReconnectionAttempts": 5,
|
|
||||||
"reconnectionDelay": 1500
|
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,9 @@
|
|||||||
"iconClass": "fa-cogs",
|
"iconClass": "fa-cogs",
|
||||||
"textClass": "visible-xs-inline",
|
"textClass": "visible-xs-inline",
|
||||||
"text": "[[global:header.admin]]",
|
"text": "[[global:header.admin]]",
|
||||||
"groups": ["administrators"]
|
"groups": ["administrators"],
|
||||||
|
"properties": {
|
||||||
|
"targetBlank": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1,47 +1,58 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const prompt = require('prompt');
|
var async = require('async');
|
||||||
const winston = require('winston');
|
var prompt = require('prompt');
|
||||||
|
var winston = require('winston');
|
||||||
|
|
||||||
const questions = {
|
var questions = {
|
||||||
redis: require('../src/database/redis').questions,
|
redis: require('../src/database/redis').questions,
|
||||||
mongo: require('../src/database/mongo').questions,
|
mongo: require('../src/database/mongo').questions,
|
||||||
postgres: require('../src/database/postgres').questions,
|
postgres: require('../src/database/postgres').questions,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async function (config) {
|
module.exports = function (config, callback) {
|
||||||
winston.info(`\nNow configuring ${config.database} database:`);
|
async.waterfall([
|
||||||
const databaseConfig = await getDatabaseConfig(config);
|
function (next) {
|
||||||
return saveDatabaseConfig(config, databaseConfig);
|
winston.info('\nNow configuring ' + config.database + ' database:');
|
||||||
|
getDatabaseConfig(config, next);
|
||||||
|
},
|
||||||
|
function (databaseConfig, next) {
|
||||||
|
saveDatabaseConfig(config, databaseConfig, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDatabaseConfig(config) {
|
function getDatabaseConfig(config, callback) {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new Error('invalid config, aborted');
|
return callback(new Error('aborted'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.database === 'redis') {
|
if (config.database === 'redis') {
|
||||||
if (config['redis:host'] && config['redis:port']) {
|
if (config['redis:host'] && config['redis:port']) {
|
||||||
return config;
|
callback(null, config);
|
||||||
|
} else {
|
||||||
|
prompt.get(questions.redis, callback);
|
||||||
}
|
}
|
||||||
return await prompt.get(questions.redis);
|
|
||||||
} else if (config.database === 'mongo') {
|
} else if (config.database === 'mongo') {
|
||||||
if ((config['mongo:host'] && config['mongo:port']) || config['mongo:uri']) {
|
if ((config['mongo:host'] && config['mongo:port']) || config['mongo:uri']) {
|
||||||
return config;
|
callback(null, config);
|
||||||
|
} else {
|
||||||
|
prompt.get(questions.mongo, callback);
|
||||||
}
|
}
|
||||||
return await prompt.get(questions.mongo);
|
|
||||||
} else if (config.database === 'postgres') {
|
} else if (config.database === 'postgres') {
|
||||||
if (config['postgres:host'] && config['postgres:port']) {
|
if (config['postgres:host'] && config['postgres:port']) {
|
||||||
return config;
|
callback(null, config);
|
||||||
|
} else {
|
||||||
|
prompt.get(questions.postgres, callback);
|
||||||
}
|
}
|
||||||
return await prompt.get(questions.postgres);
|
} else {
|
||||||
|
return callback(new Error('unknown database : ' + config.database));
|
||||||
}
|
}
|
||||||
throw new Error(`unknown database : ${config.database}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveDatabaseConfig(config, databaseConfig) {
|
function saveDatabaseConfig(config, databaseConfig, callback) {
|
||||||
if (!databaseConfig) {
|
if (!databaseConfig) {
|
||||||
throw new Error('invalid config, aborted');
|
return callback(new Error('aborted'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate redis properties into redis object
|
// Translate redis properties into redis object
|
||||||
@@ -75,13 +86,13 @@ function saveDatabaseConfig(config, databaseConfig) {
|
|||||||
ssl: databaseConfig['postgres:ssl'],
|
ssl: databaseConfig['postgres:ssl'],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`unknown database : ${config.database}`);
|
return callback(new Error('unknown database : ' + config.database));
|
||||||
}
|
}
|
||||||
|
|
||||||
const allQuestions = questions.redis.concat(questions.mongo).concat(questions.postgres);
|
var 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];
|
delete config[allQuestions[x].name];
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
callback(null, config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "nodebb",
|
"name": "nodebb",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"description": "NodeBB Forum",
|
"description": "NodeBB Forum",
|
||||||
"version": "1.19.1",
|
"version": "1.13.0",
|
||||||
"homepage": "http://www.nodebb.org",
|
"homepage": "http://www.nodebb.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -12,159 +12,146 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node loader.js",
|
"start": "node loader.js",
|
||||||
"lint": "eslint --cache ./nodebb .",
|
"lint": "eslint --cache ./nodebb .",
|
||||||
|
"pretest": "npm run lint",
|
||||||
"test": "nyc --reporter=html --reporter=text-summary mocha",
|
"test": "nyc --reporter=html --reporter=text-summary mocha",
|
||||||
"coverage": "nyc report --reporter=text-lcov > ./coverage/lcov.info",
|
|
||||||
"coveralls": "nyc report --reporter=text-lcov | coveralls && rm -r coverage"
|
"coveralls": "nyc report --reporter=text-lcov | coveralls && rm -r coverage"
|
||||||
},
|
},
|
||||||
"nyc": {
|
"husky": {
|
||||||
"exclude": [
|
"hooks": {
|
||||||
"src/upgrades/*",
|
"pre-commit": "lint-staged",
|
||||||
"test/*"
|
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||||
]
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.js": [
|
"*.js": [
|
||||||
"eslint --fix"
|
"eslint --fix",
|
||||||
|
"git add"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adactive/bootstrap-tagsinput": "0.8.2",
|
"ace-builds": "^1.2.9",
|
||||||
"ace-builds": "1.4.13",
|
"archiver": "^3.0.0",
|
||||||
"archiver": "5.3.0",
|
"async": "^3.0.1",
|
||||||
"async": "3.2.3",
|
"autoprefixer": "^9.4.6",
|
||||||
"autoprefixer": "10.4.2",
|
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"benchpressjs": "2.4.3",
|
"benchpressjs": "^2.0.0",
|
||||||
"body-parser": "1.19.1",
|
"body-parser": "^1.18.2",
|
||||||
"bootbox": "5.5.2",
|
"bootstrap": "^3.4.0",
|
||||||
"bootstrap": "3.4.1",
|
"bootswatch": "git://github.com/thomaspark/bootswatch.git#c41a8f066feb8950c6f9c6bcf5a3c37d1085404e",
|
||||||
"chart.js": "2.9.4",
|
"chart.js": "^2.7.1",
|
||||||
"cli-graph": "3.2.2",
|
"cli-graph": "^3.2.2",
|
||||||
"clipboard": "2.0.8",
|
"clipboard": "^2.0.1",
|
||||||
"colors": "1.4.0",
|
"colors": "^1.1.2",
|
||||||
"commander": "7.2.0",
|
"commander": "^3.0.0",
|
||||||
"compare-versions": "4.1.3",
|
"compression": "^1.7.1",
|
||||||
"compression": "1.7.4",
|
"connect-ensure-login": "^0.1.1",
|
||||||
"connect-flash": "0.1.1",
|
"connect-flash": "^0.1.1",
|
||||||
"connect-mongo": "4.6.0",
|
"connect-mongo": "3.2.0",
|
||||||
"connect-multiparty": "2.2.0",
|
"connect-multiparty": "^2.1.0",
|
||||||
"connect-pg-simple": "7.0.0",
|
"connect-pg-simple": "^6.0.0",
|
||||||
"connect-redis": "6.0.0",
|
"connect-redis": "4.0.3",
|
||||||
"cookie-parser": "1.4.6",
|
"cookie-parser": "^1.4.3",
|
||||||
"cron": "1.8.2",
|
"cron": "^1.3.0",
|
||||||
"cropperjs": "1.5.12",
|
"cropperjs": "^1.2.2",
|
||||||
"csurf": "1.11.0",
|
"csurf": "^1.9.0",
|
||||||
"daemon": "1.1.0",
|
"daemon": "^1.1.0",
|
||||||
"diff": "5.0.0",
|
"diff": "^4.0.1",
|
||||||
"express": "4.17.2",
|
"express": "^4.16.2",
|
||||||
"express-session": "1.17.2",
|
"express-session": "^1.15.6",
|
||||||
"express-useragent": "1.0.15",
|
"express-useragent": "^1.0.12",
|
||||||
"graceful-fs": "4.2.9",
|
"graceful-fs": "^4.1.11",
|
||||||
"helmet": "4.6.0",
|
"helmet": "^3.11.0",
|
||||||
"html-to-text": "8.1.0",
|
"html-to-text": "^5.0.0",
|
||||||
"ipaddr.js": "2.0.1",
|
"ipaddr.js": "^1.5.4",
|
||||||
"jquery": "3.6.0",
|
"jquery": "^3.2.1",
|
||||||
"jquery-deserialize": "2.0.0",
|
"jsesc": "2.5.2",
|
||||||
"jquery-form": "4.3.0",
|
"json-2-csv": "^3.0.0",
|
||||||
"jquery-serializeobject": "1.0.0",
|
"jsonwebtoken": "^8.4.0",
|
||||||
"jquery-ui": "1.13.1",
|
"less": "^3.10.3",
|
||||||
"jsesc": "3.0.2",
|
"lodash": "^4.17.15",
|
||||||
"json2csv": "5.0.6",
|
"logrotate-stream": "^0.2.5",
|
||||||
"jsonwebtoken": "8.5.1",
|
"lru-cache": "5.1.1",
|
||||||
"less": "3.13.1",
|
"material-design-lite": "^1.3.0",
|
||||||
"lodash": "4.17.21",
|
"mime": "^2.2.0",
|
||||||
"logrotate-stream": "0.2.8",
|
"mkdirp": "^0.5.1",
|
||||||
"lru-cache": "6.0.0",
|
"mongodb": "3.4.0",
|
||||||
"material-design-lite": "1.3.0",
|
"morgan": "^1.9.1",
|
||||||
"mime": "3.0.0",
|
"mousetrap": "^1.6.1",
|
||||||
"mkdirp": "1.0.4",
|
"mubsub-nbb": "^1.5.1",
|
||||||
"mongodb": "4.3.1",
|
"nconf": "^0.10.0",
|
||||||
"morgan": "1.10.0",
|
"nodebb-plugin-composer-default": "6.3.20",
|
||||||
"mousetrap": "1.6.5",
|
"nodebb-plugin-dbsearch": "4.0.7",
|
||||||
"multiparty": "4.2.3",
|
"nodebb-plugin-emoji": "^3.0.0",
|
||||||
"@nodebb/bootswatch": "3.4.2",
|
"nodebb-plugin-emoji-android": "2.0.0",
|
||||||
"nconf": "0.11.3",
|
"nodebb-plugin-markdown": "8.11.0",
|
||||||
"nodebb-plugin-2factor": "3.0.4",
|
"nodebb-plugin-mentions": "2.7.3",
|
||||||
"nodebb-plugin-composer-default": "7.0.18",
|
"nodebb-plugin-soundpack-default": "1.0.0",
|
||||||
"nodebb-plugin-dbsearch": "5.1.1",
|
"nodebb-plugin-spam-be-gone": "0.6.7",
|
||||||
"nodebb-plugin-emoji": "3.5.4",
|
"nodebb-rewards-essentials": "0.1.2",
|
||||||
"nodebb-plugin-emoji-android": "2.0.5",
|
"nodebb-theme-lavender": "5.0.11",
|
||||||
"nodebb-plugin-markdown": "8.14.6",
|
"nodebb-theme-persona": "10.1.30",
|
||||||
"nodebb-plugin-mentions": "3.0.4",
|
"nodebb-theme-slick": "1.2.28",
|
||||||
"nodebb-plugin-spam-be-gone": "0.7.12",
|
"nodebb-theme-vanilla": "11.1.12",
|
||||||
"nodebb-rewards-essentials": "0.2.1",
|
"nodebb-widget-essentials": "4.0.17",
|
||||||
"nodebb-theme-lavender": "5.3.2",
|
"nodemailer": "^6.0.0",
|
||||||
"nodebb-theme-persona": "11.3.18",
|
"passport": "^0.4.0",
|
||||||
"nodebb-theme-slick": "1.4.23",
|
|
||||||
"nodebb-theme-vanilla": "12.1.16",
|
|
||||||
"nodebb-widget-essentials": "5.0.4",
|
|
||||||
"nodemailer": "6.7.2",
|
|
||||||
"nprogress": "0.2.0",
|
|
||||||
"passport": "0.5.2",
|
|
||||||
"passport-http-bearer": "1.0.1",
|
|
||||||
"passport-local": "1.0.0",
|
"passport-local": "1.0.0",
|
||||||
"pg": "8.7.1",
|
"pg": "^7.4.0",
|
||||||
"pg-cursor": "2.7.1",
|
"pg-cursor": "^2.0.0",
|
||||||
"postcss": "8.4.5",
|
"postcss": "7.0.21",
|
||||||
"postcss-clean": "1.2.0",
|
"postcss-clean": "1.1.0",
|
||||||
"prompt": "1.2.1",
|
"promise-polyfill": "^8.0.0",
|
||||||
"ioredis": "4.28.3",
|
"prompt": "^1.0.0",
|
||||||
"request": "2.88.2",
|
"redis": "2.8.0",
|
||||||
"request-promise-native": "1.0.9",
|
"request": "2.88.0",
|
||||||
"requirejs": "2.3.6",
|
"rimraf": "3.0.0",
|
||||||
"rimraf": "3.0.2",
|
"rss": "^1.2.2",
|
||||||
"rss": "1.2.2",
|
"sanitize-html": "^1.16.3",
|
||||||
"sanitize-html": "2.6.1",
|
"semver": "^7.0.0",
|
||||||
"semver": "7.3.5",
|
"serve-favicon": "^2.4.5",
|
||||||
"serve-favicon": "2.5.0",
|
"sharp": "0.23.4",
|
||||||
"sharp": "0.29.3",
|
"sitemap": "^5.0.0",
|
||||||
"sitemap": "7.1.0",
|
"socket.io": "2.3.0",
|
||||||
"slideout": "1.0.1",
|
"socket.io-adapter-cluster": "^1.0.1",
|
||||||
"socket.io": "4.4.1",
|
"socket.io-adapter-mongo": "^2.0.4",
|
||||||
"socket.io-adapter-cluster": "1.0.1",
|
"socket.io-adapter-postgres": "^1.2.1",
|
||||||
"socket.io-client": "4.4.1",
|
"socket.io-client": "2.3.0",
|
||||||
"@socket.io/redis-adapter": "7.1.0",
|
"socket.io-redis": "5.2.0",
|
||||||
"sortablejs": "1.14.0",
|
"socketio-wildcard": "2.0.0",
|
||||||
"spdx-license-list": "6.4.0",
|
"spdx-license-list": "^6.0.0",
|
||||||
"spider-detector": "2.0.0",
|
"spider-detector": "2.0.0",
|
||||||
"textcomplete": "0.18.2",
|
"textcomplete": "^0.17.1",
|
||||||
"textcomplete.contenteditable": "0.1.1",
|
"textcomplete.contenteditable": "^0.1.1",
|
||||||
"timeago": "1.6.7",
|
"toobusy-js": "^0.5.1",
|
||||||
"tinycon": "0.6.8",
|
"uglify-es": "^3.3.9",
|
||||||
"toobusy-js": "0.5.1",
|
"validator": "12.1.0",
|
||||||
"uglify-es": "3.3.9",
|
"winston": "3.2.1",
|
||||||
"validator": "13.7.0",
|
"xml": "^1.0.1",
|
||||||
"visibilityjs": "2.0.2",
|
"xregexp": "^4.1.1",
|
||||||
"winston": "3.4.0",
|
"zxcvbn": "^4.4.2"
|
||||||
"xml": "1.0.1",
|
|
||||||
"xregexp": "5.1.0",
|
|
||||||
"yargs": "17.3.1",
|
|
||||||
"zxcvbn": "4.4.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.0.3",
|
"@commitlint/cli": "8.2.0",
|
||||||
"@commitlint/cli": "16.1.0",
|
"@commitlint/config-angular": "8.2.0",
|
||||||
"@commitlint/config-angular": "16.0.0",
|
"coveralls": "3.0.9",
|
||||||
"coveralls": "3.1.1",
|
"eslint": "6.7.0",
|
||||||
"eslint": "8.7.0",
|
"eslint-config-airbnb-base": "14.0.0",
|
||||||
"eslint-config-nodebb": "0.1.1",
|
"eslint-plugin-import": "2.18.2",
|
||||||
"eslint-plugin-import": "2.25.4",
|
"grunt": "1.0.4",
|
||||||
"grunt": "1.4.1",
|
|
||||||
"grunt-contrib-watch": "1.1.0",
|
"grunt-contrib-watch": "1.1.0",
|
||||||
"husky": "7.0.4",
|
"husky": "3.1.0",
|
||||||
"jsdom": "19.0.0",
|
"jsdom": "15.2.1",
|
||||||
"lint-staged": "12.2.2",
|
"lint-staged": "9.4.2",
|
||||||
"mocha": "9.1.4",
|
"mocha": "6.2.2",
|
||||||
"mocha-lcov-reporter": "1.3.0",
|
"mocha-lcov-reporter": "1.3.0",
|
||||||
"mockdate": "3.0.5",
|
"nyc": "14.1.1",
|
||||||
"nyc": "15.1.0",
|
"smtp-server": "3.5.0"
|
||||||
"smtp-server": "3.9.0"
|
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/NodeBB/NodeBB/issues"
|
"url": "https://github.com/NodeBB/NodeBB/issues"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=8"
|
||||||
},
|
},
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
{
|
{
|
||||||
|
|||||||
252
install/web.js
@@ -1,30 +1,27 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const winston = require('winston');
|
var winston = require('winston');
|
||||||
const express = require('express');
|
var express = require('express');
|
||||||
const bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
const fs = require('fs');
|
var fs = require('fs');
|
||||||
const path = require('path');
|
var path = require('path');
|
||||||
const childProcess = require('child_process');
|
var childProcess = require('child_process');
|
||||||
const less = require('less');
|
var less = require('less');
|
||||||
|
var async = require('async');
|
||||||
|
var uglify = require('uglify-es');
|
||||||
|
var nconf = require('nconf');
|
||||||
|
var Benchpress = require('benchpressjs');
|
||||||
|
|
||||||
const uglify = require('uglify-es');
|
var app = express();
|
||||||
const nconf = require('nconf');
|
var server;
|
||||||
|
|
||||||
const Benchpress = require('benchpressjs');
|
var formats = [
|
||||||
const mkdirp = require('mkdirp');
|
|
||||||
const { paths } = require('../src/constants');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
let server;
|
|
||||||
|
|
||||||
const formats = [
|
|
||||||
winston.format.colorize(),
|
winston.format.colorize(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const timestampFormat = winston.format((info) => {
|
const timestampFormat = winston.format((info) => {
|
||||||
const dateString = `${new Date().toISOString()} [${global.process.pid}]`;
|
var dateString = new Date().toISOString() + ' [' + global.process.pid + ']';
|
||||||
info.level = `${dateString} - ${info.level}`;
|
info.level = dateString + ' - ' + info.level;
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
formats.push(timestampFormat());
|
formats.push(timestampFormat());
|
||||||
@@ -45,57 +42,55 @@ winston.configure({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const web = module.exports;
|
var web = module.exports;
|
||||||
|
|
||||||
const scripts = [
|
var scripts = [
|
||||||
'node_modules/jquery/dist/jquery.js',
|
'node_modules/jquery/dist/jquery.js',
|
||||||
'node_modules/xregexp/xregexp-all.js',
|
'public/vendor/xregexp/xregexp.js',
|
||||||
'public/src/modules/slugify.js',
|
'public/vendor/xregexp/unicode/unicode-base.js',
|
||||||
'public/src/utils.js',
|
'public/src/utils.js',
|
||||||
'public/src/installer/install.js',
|
'public/src/installer/install.js',
|
||||||
'node_modules/zxcvbn/dist/zxcvbn.js',
|
'node_modules/zxcvbn/dist/zxcvbn.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
let installing = false;
|
var installing = false;
|
||||||
let success = false;
|
var success = false;
|
||||||
let error = false;
|
var error = false;
|
||||||
let launchUrl;
|
var launchUrl;
|
||||||
|
|
||||||
const viewsDir = path.join(paths.baseDir, 'build/public/templates');
|
web.install = function (port) {
|
||||||
|
|
||||||
web.install = async function (port) {
|
|
||||||
port = port || 4567;
|
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(express.static('public', {}));
|
||||||
app.engine('tpl', (filepath, options, callback) => {
|
app.engine('tpl', function (filepath, options, callback) {
|
||||||
filepath = filepath.replace(/\.tpl$/, '.js');
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
Benchpress.__express(filepath, options, callback);
|
fs.readFile(filepath, 'utf-8', next);
|
||||||
|
},
|
||||||
|
function (buffer, next) {
|
||||||
|
Benchpress.compileParse(buffer.toString(), options, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
});
|
});
|
||||||
app.set('view engine', 'tpl');
|
app.set('view engine', 'tpl');
|
||||||
app.set('views', viewsDir);
|
app.set('views', path.join(__dirname, '../src/views'));
|
||||||
app.use(bodyParser.urlencoded({
|
app.use(bodyParser.urlencoded({
|
||||||
extended: true,
|
extended: true,
|
||||||
}));
|
}));
|
||||||
try {
|
|
||||||
await Promise.all([
|
async.parallel([compileLess, compileJS, copyCSS, loadDefaults], function (err) {
|
||||||
compileTemplate(),
|
if (err) {
|
||||||
compileLess(),
|
winston.error(err);
|
||||||
compileJS(),
|
}
|
||||||
copyCSS(),
|
|
||||||
loadDefaults(),
|
|
||||||
]);
|
|
||||||
setupRoutes();
|
setupRoutes();
|
||||||
launchExpress(port);
|
launchExpress(port);
|
||||||
} catch (err) {
|
});
|
||||||
winston.error(err.stack);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function launchExpress(port) {
|
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);
|
winston.info('Web installer listening on http://%s:%s', '0.0.0.0', port);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -113,9 +108,11 @@ function ping(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function welcome(req, res) {
|
function welcome(req, res) {
|
||||||
const dbs = ['redis', 'mongo', 'postgres'];
|
var dbs = ['redis', 'mongo', 'postgres'];
|
||||||
const databases = dbs.map((databaseName) => {
|
var databases = dbs.map(function (databaseName) {
|
||||||
const questions = require(`../src/database/${databaseName}`).questions.filter(question => question && !question.hideOnWebInstall);
|
var questions = require('../src/database/' + databaseName).questions.filter(function (question) {
|
||||||
|
return question && !question.hideOnWebInstall;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: databaseName,
|
name: databaseName,
|
||||||
@@ -123,10 +120,10 @@ function welcome(req, res) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaults = require('./data/defaults.json');
|
var defaults = require('./data/defaults');
|
||||||
|
|
||||||
res.render('install/index', {
|
res.render('install/index', {
|
||||||
url: nconf.get('url') || (`${req.protocol}://${req.get('host')}`),
|
url: nconf.get('url') || (req.protocol + '://' + req.get('host')),
|
||||||
launchUrl: launchUrl,
|
launchUrl: launchUrl,
|
||||||
skipGeneralSetup: !!nconf.get('url'),
|
skipGeneralSetup: !!nconf.get('url'),
|
||||||
databases: databases,
|
databases: databases,
|
||||||
@@ -146,23 +143,23 @@ function install(req, res) {
|
|||||||
}
|
}
|
||||||
req.setTimeout(0);
|
req.setTimeout(0);
|
||||||
installing = true;
|
installing = true;
|
||||||
const setupEnvVars = nconf.get();
|
var setupEnvVars = nconf.get();
|
||||||
for (const [key, value] of Object.entries(req.body)) {
|
for (var i in req.body) {
|
||||||
if (!process.env.hasOwnProperty(key)) {
|
if (req.body.hasOwnProperty(i) && !process.env.hasOwnProperty(i)) {
|
||||||
setupEnvVars[key.replace(':', '__')] = value;
|
setupEnvVars[i.replace(':', '__')] = req.body[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flatten any objects in setupEnvVars
|
// Flatten any objects in setupEnvVars
|
||||||
const pushToRoot = function (parentKey, key) {
|
const pushToRoot = function (parentKey, key) {
|
||||||
setupEnvVars[`${parentKey}__${key}`] = setupEnvVars[parentKey][key];
|
setupEnvVars[parentKey + '__' + key] = setupEnvVars[parentKey][key];
|
||||||
};
|
};
|
||||||
for (const [parentKey, value] of Object.entries(setupEnvVars)) {
|
for (var j in setupEnvVars) {
|
||||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
if (setupEnvVars.hasOwnProperty(j) && typeof setupEnvVars[j] === 'object' && setupEnvVars[j] !== null && !Array.isArray(setupEnvVars[j])) {
|
||||||
Object.keys(value).forEach(key => pushToRoot(parentKey, key));
|
Object.keys(setupEnvVars[j]).forEach(pushToRoot.bind(null, j));
|
||||||
delete setupEnvVars[parentKey];
|
delete setupEnvVars[j];
|
||||||
} else if (Array.isArray(value)) {
|
} else if (Array.isArray(setupEnvVars[j])) {
|
||||||
setupEnvVars[parentKey] = JSON.stringify(value);
|
setupEnvVars[j] = JSON.stringify(setupEnvVars[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,11 +167,11 @@ function install(req, res) {
|
|||||||
winston.info(setupEnvVars);
|
winston.info(setupEnvVars);
|
||||||
launchUrl = setupEnvVars.url;
|
launchUrl = setupEnvVars.url;
|
||||||
|
|
||||||
const child = require('child_process').fork('app', ['--setup'], {
|
var child = require('child_process').fork('app', ['--setup'], {
|
||||||
env: setupEnvVars,
|
env: setupEnvVars,
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on('close', (data) => {
|
child.on('close', function (data) {
|
||||||
installing = false;
|
installing = false;
|
||||||
success = data === 0;
|
success = data === 0;
|
||||||
error = data !== 0;
|
error = data !== 0;
|
||||||
@@ -183,12 +180,11 @@ function install(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function launch(req, res) {
|
function launch(req, res) {
|
||||||
try {
|
|
||||||
res.json({});
|
res.json({});
|
||||||
server.close();
|
server.close();
|
||||||
req.setTimeout(0);
|
req.setTimeout(0);
|
||||||
let child;
|
var child;
|
||||||
|
|
||||||
if (!nconf.get('launchCmd')) {
|
if (!nconf.get('launchCmd')) {
|
||||||
child = childProcess.spawn('node', ['loader.js'], {
|
child = childProcess.spawn('node', ['loader.js'], {
|
||||||
@@ -208,91 +204,93 @@ async function launch(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const filesToDelete = [
|
var filesToDelete = [
|
||||||
'installer.css',
|
'installer.css',
|
||||||
'installer.min.js',
|
'installer.min.js',
|
||||||
'bootstrap.min.css',
|
'bootstrap.min.css',
|
||||||
];
|
];
|
||||||
await Promise.all(
|
|
||||||
filesToDelete.map(
|
async.each(filesToDelete, function (filename, next) {
|
||||||
filename => fs.promises.unlink(path.join(__dirname, '../public', filename))
|
fs.unlink(path.join(__dirname, '../public', filename), next);
|
||||||
)
|
}, function (err) {
|
||||||
);
|
if (err) {
|
||||||
|
winston.warn('Unable to remove installer files');
|
||||||
|
}
|
||||||
|
|
||||||
child.unref();
|
child.unref();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (err) {
|
});
|
||||||
winston.error(err.stack);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is necessary because otherwise the compiled templates won't be available on a clean install
|
function compileLess(callback) {
|
||||||
async function compileTemplate() {
|
fs.readFile(path.join(__dirname, '../public/less/install.less'), function (err, style) {
|
||||||
const sourceFile = path.join(__dirname, '../src/views/install/index.tpl');
|
if (err) {
|
||||||
const destTpl = path.join(viewsDir, 'install/index.tpl');
|
return winston.error('Unable to read LESS install file: ', err);
|
||||||
const destJs = path.join(viewsDir, 'install/index.js');
|
|
||||||
|
|
||||||
const source = await fs.promises.readFile(sourceFile, 'utf8');
|
|
||||||
|
|
||||||
const [compiled] = await Promise.all([
|
|
||||||
Benchpress.precompile(source, { filename: 'install/index.tpl' }),
|
|
||||||
mkdirp(path.dirname(destJs)),
|
|
||||||
]);
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
fs.promises.writeFile(destJs, compiled),
|
|
||||||
fs.promises.writeFile(destTpl, source),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function compileLess() {
|
less.render(style.toString(), function (err, css) {
|
||||||
try {
|
if (err) {
|
||||||
const installSrc = path.join(__dirname, '../public/less/install.less');
|
return winston.error('Unable to compile LESS: ', err);
|
||||||
const style = await fs.promises.readFile(installSrc);
|
|
||||||
const css = await less.render(String(style), { filename: path.resolve(installSrc) });
|
|
||||||
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), css.css);
|
|
||||||
} catch (err) {
|
|
||||||
winston.error(`Unable to compile LESS: \n${err.stack}`);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function compileJS() {
|
fs.writeFile(path.join(__dirname, '../public/installer.css'), css.css, callback);
|
||||||
let code = '';
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileJS(callback) {
|
||||||
|
var code = '';
|
||||||
|
async.eachSeries(scripts, function (srcPath, next) {
|
||||||
|
fs.readFile(path.join(__dirname, '..', srcPath), function (err, buffer) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
code += buffer.toString();
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
}
|
}
|
||||||
const minified = uglify.minify(code, {
|
try {
|
||||||
|
var minified = uglify.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
});
|
});
|
||||||
if (!minified.code) {
|
if (!minified.code) {
|
||||||
throw new Error('[[error:failed-to-minify]]');
|
return callback(new Error('[[error:failed-to-minify]]'));
|
||||||
}
|
}
|
||||||
await fs.promises.writeFile(path.join(__dirname, '../public/installer.min.js'), minified.code);
|
fs.writeFile(path.join(__dirname, '../public/installer.min.js'), minified.code, callback);
|
||||||
|
} catch (e) {
|
||||||
|
callback(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyCSS() {
|
function copyCSS(next) {
|
||||||
const src = await fs.promises.readFile(
|
async.waterfall([
|
||||||
path.join(__dirname, '../node_modules/bootstrap/dist/css/bootstrap.min.css'), 'utf8'
|
function (next) {
|
||||||
);
|
fs.readFile(path.join(__dirname, '../node_modules/bootstrap/dist/css/bootstrap.min.css'), 'utf8', next);
|
||||||
await fs.promises.writeFile(path.join(__dirname, '../public/bootstrap.min.css'), src);
|
},
|
||||||
|
function (src, next) {
|
||||||
|
fs.writeFile(path.join(__dirname, '../public/bootstrap.min.css'), src, next);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadDefaults() {
|
function loadDefaults(next) {
|
||||||
const setupDefaultsPath = path.join(__dirname, '../setup.json');
|
var setupDefaultsPath = path.join(__dirname, '../setup.json');
|
||||||
try {
|
fs.access(setupDefaultsPath, fs.constants.F_OK | fs.constants.R_OK, function (err) {
|
||||||
await fs.promises.access(setupDefaultsPath, fs.constants.F_OK + fs.constants.R_OK);
|
if (err) {
|
||||||
} catch (err) {
|
|
||||||
// setup.json not found or inaccessible, proceed with no defaults
|
// setup.json not found or inaccessible, proceed with no defaults
|
||||||
if (err.code !== 'ENOENT') {
|
return setImmediate(next);
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
winston.info('[installer] Found setup.json, populating default values');
|
winston.info('[installer] Found setup.json, populating default values');
|
||||||
nconf.file({
|
nconf.file({
|
||||||
file: setupDefaultsPath,
|
file: setupDefaultsPath,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
132
loader.js
@@ -1,78 +1,82 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
const fs = require('fs');
|
var fs = require('fs');
|
||||||
const url = require('url');
|
var url = require('url');
|
||||||
const path = require('path');
|
var path = require('path');
|
||||||
const { fork } = require('child_process');
|
var fork = require('child_process').fork;
|
||||||
const logrotate = require('logrotate-stream');
|
var async = require('async');
|
||||||
const mkdirp = require('mkdirp');
|
var logrotate = require('logrotate-stream');
|
||||||
|
var mkdirp = require('mkdirp');
|
||||||
|
|
||||||
const file = require('./src/file');
|
var file = require('./src/file');
|
||||||
const pkg = require('./package.json');
|
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({
|
nconf.argv().env().file({
|
||||||
file: pathToConfig,
|
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)) {
|
if (!fs.existsSync(logDir)) {
|
||||||
mkdirp.sync(path.dirname(outputLogFilePath));
|
mkdirp.sync(path.dirname(outputLogFilePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
var output = logrotate({ file: outputLogFilePath, size: '1m', keep: 3, compress: true });
|
||||||
const silent = nconf.get('silent') === 'false' ? false : nconf.get('silent') !== false;
|
var silent = nconf.get('silent') === 'false' ? false : nconf.get('silent') !== false;
|
||||||
let numProcs;
|
var numProcs;
|
||||||
const workers = [];
|
var workers = [];
|
||||||
const Loader = {
|
var Loader = {
|
||||||
timesStarted: 0,
|
timesStarted: 0,
|
||||||
};
|
};
|
||||||
const appPath = path.join(__dirname, 'app.js');
|
var appPath = path.join(__dirname, 'app.js');
|
||||||
|
|
||||||
Loader.init = function () {
|
Loader.init = function (callback) {
|
||||||
if (silent) {
|
if (silent) {
|
||||||
console.log = (...args) => {
|
console.log = function () {
|
||||||
output.write(`${args.join(' ')}\n`);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
output.write(args.join(' ') + '\n');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('SIGHUP', Loader.restart);
|
process.on('SIGHUP', Loader.restart);
|
||||||
process.on('SIGTERM', Loader.stop);
|
process.on('SIGTERM', Loader.stop);
|
||||||
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
Loader.displayStartupMessages = function () {
|
Loader.displayStartupMessages = function (callback) {
|
||||||
console.log('');
|
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 program comes with ABSOLUTELY NO WARRANTY.');
|
||||||
console.log('This is free software, and you are welcome to redistribute it under certain conditions.');
|
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('For the full license, please visit: http://www.gnu.org/copyleft/gpl.html');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
Loader.addWorkerEvents = function (worker) {
|
Loader.addWorkerEvents = function (worker) {
|
||||||
worker.on('exit', (code, signal) => {
|
worker.on('exit', function (code, signal) {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
if (Loader.timesStarted < numProcs * 3) {
|
if (Loader.timesStarted < numProcs * 3) {
|
||||||
Loader.timesStarted += 1;
|
Loader.timesStarted += 1;
|
||||||
if (Loader.crashTimer) {
|
if (Loader.crashTimer) {
|
||||||
clearTimeout(Loader.crashTimer);
|
clearTimeout(Loader.crashTimer);
|
||||||
}
|
}
|
||||||
Loader.crashTimer = setTimeout(() => {
|
Loader.crashTimer = setTimeout(function () {
|
||||||
Loader.timesStarted = 0;
|
Loader.timesStarted = 0;
|
||||||
}, 10000);
|
}, 10000);
|
||||||
} else {
|
} else {
|
||||||
console.log(`${numProcs * 3} restarts in 10 seconds, most likely an error on startup. Halting.`);
|
console.log((numProcs * 3) + ' restarts in 10 seconds, most likely an error on startup. Halting.');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[cluster] Child Process (${worker.pid}) has exited (code: ${code}, signal: ${signal})`);
|
console.log('[cluster] Child Process (' + worker.pid + ') has exited (code: ' + code + ', signal: ' + signal + ')');
|
||||||
if (!(worker.suicide || code === 0)) {
|
if (!(worker.suicide || code === 0)) {
|
||||||
console.log('[cluster] Spinning up another process...');
|
console.log('[cluster] Spinning up another process...');
|
||||||
|
|
||||||
@@ -80,7 +84,7 @@ Loader.addWorkerEvents = function (worker) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.on('message', (message) => {
|
worker.on('message', function (message) {
|
||||||
if (message && typeof message === 'object' && message.action) {
|
if (message && typeof message === 'object' && message.action) {
|
||||||
switch (message.action) {
|
switch (message.action) {
|
||||||
case 'restart':
|
case 'restart':
|
||||||
@@ -88,12 +92,12 @@ Loader.addWorkerEvents = function (worker) {
|
|||||||
Loader.restart();
|
Loader.restart();
|
||||||
break;
|
break;
|
||||||
case 'pubsub':
|
case 'pubsub':
|
||||||
workers.forEach((w) => {
|
workers.forEach(function (w) {
|
||||||
w.send(message);
|
w.send(message);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'socket.io':
|
case 'socket.io':
|
||||||
workers.forEach((w) => {
|
workers.forEach(function (w) {
|
||||||
if (w !== worker) {
|
if (w !== worker) {
|
||||||
w.send(message);
|
w.send(message);
|
||||||
}
|
}
|
||||||
@@ -104,28 +108,32 @@ Loader.addWorkerEvents = function (worker) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Loader.start = function () {
|
Loader.start = function (callback) {
|
||||||
numProcs = getPorts().length;
|
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);
|
forkWorker(x, x === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function forkWorker(index, isPrimary) {
|
function forkWorker(index, isPrimary) {
|
||||||
const ports = getPorts();
|
var ports = getPorts();
|
||||||
const args = [];
|
var args = [];
|
||||||
|
|
||||||
if (!ports[index]) {
|
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.isPrimary = isPrimary;
|
||||||
process.env.isCluster = nconf.get('isCluster') || ports.length > 1;
|
process.env.isCluster = nconf.get('isCluster') || ports.length > 1;
|
||||||
process.env.port = ports[index];
|
process.env.port = ports[index];
|
||||||
|
|
||||||
const worker = fork(appPath, args, {
|
var worker = fork(appPath, args, {
|
||||||
silent: silent,
|
silent: silent,
|
||||||
env: process.env,
|
env: process.env,
|
||||||
});
|
});
|
||||||
@@ -138,20 +146,20 @@ function forkWorker(index, isPrimary) {
|
|||||||
Loader.addWorkerEvents(worker);
|
Loader.addWorkerEvents(worker);
|
||||||
|
|
||||||
if (silent) {
|
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.stdout.pipe(output);
|
||||||
worker.stderr.pipe(output);
|
worker.stderr.pipe(output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPorts() {
|
function getPorts() {
|
||||||
const _url = nconf.get('url');
|
var _url = nconf.get('url');
|
||||||
if (!_url) {
|
if (!_url) {
|
||||||
console.log('[cluster] url is undefined, please check your config.json');
|
console.log('[cluster] url is undefined, please check your config.json');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
const urlObject = url.parse(_url);
|
var urlObject = url.parse(_url);
|
||||||
let port = nconf.get('PORT') || nconf.get('port') || urlObject.port || 4567;
|
var port = nconf.get('PORT') || nconf.get('port') || urlObject.port || 4567;
|
||||||
if (!Array.isArray(port)) {
|
if (!Array.isArray(port)) {
|
||||||
port = [port];
|
port = [port];
|
||||||
}
|
}
|
||||||
@@ -164,13 +172,13 @@ Loader.restart = function () {
|
|||||||
nconf.remove('file');
|
nconf.remove('file');
|
||||||
nconf.use('file', { file: pathToConfig });
|
nconf.use('file', { file: pathToConfig });
|
||||||
|
|
||||||
fs.readFile(pathToConfig, { encoding: 'utf-8' }, (err, configFile) => {
|
fs.readFile(pathToConfig, { encoding: 'utf-8' }, function (err, configFile) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Error reading config');
|
console.error('Error reading config');
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
const conf = JSON.parse(configFile);
|
var conf = JSON.parse(configFile);
|
||||||
|
|
||||||
nconf.stores.env.readOnly = false;
|
nconf.stores.env.readOnly = false;
|
||||||
nconf.set('url', conf.url);
|
nconf.set('url', conf.url);
|
||||||
@@ -193,13 +201,13 @@ Loader.stop = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function killWorkers() {
|
function killWorkers() {
|
||||||
workers.forEach((worker) => {
|
workers.forEach(function (worker) {
|
||||||
worker.suicide = true;
|
worker.suicide = true;
|
||||||
worker.kill();
|
worker.kill();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.open(pathToConfig, 'r', (err) => {
|
fs.open(pathToConfig, 'r', function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
// No config detected, kickstart web installer
|
// No config detected, kickstart web installer
|
||||||
fork('app');
|
fork('app');
|
||||||
@@ -208,26 +216,13 @@ fs.open(pathToConfig, 'r', (err) => {
|
|||||||
|
|
||||||
if (nconf.get('daemon') !== 'false' && nconf.get('daemon') !== false) {
|
if (nconf.get('daemon') !== 'false' && nconf.get('daemon') !== false) {
|
||||||
if (file.existsSync(pidFilePath)) {
|
if (file.existsSync(pidFilePath)) {
|
||||||
let pid = 0;
|
|
||||||
try {
|
try {
|
||||||
pid = fs.readFileSync(pidFilePath, { encoding: 'utf-8' });
|
var pid = fs.readFileSync(pidFilePath, { encoding: 'utf-8' });
|
||||||
if (pid) {
|
|
||||||
process.kill(pid, 0);
|
process.kill(pid, 0);
|
||||||
console.info(`Process "${pid}" from pidfile already running, exiting`);
|
|
||||||
process.exit();
|
process.exit();
|
||||||
} else {
|
} catch (e) {
|
||||||
console.info(`Invalid pid "${pid}" from pidfile, deleting pidfile`);
|
|
||||||
fs.unlinkSync(pidFilePath);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require('daemon')({
|
require('daemon')({
|
||||||
@@ -236,14 +231,17 @@ fs.open(pathToConfig, 'r', (err) => {
|
|||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.writeFileSync(pidFilePath, String(process.pid));
|
fs.writeFileSync(pidFilePath, process.pid);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
Loader.init();
|
async.series([
|
||||||
Loader.displayStartupMessages();
|
Loader.init,
|
||||||
Loader.start();
|
Loader.displayStartupMessages,
|
||||||
} catch (err) {
|
Loader.start,
|
||||||
|
], function (err) {
|
||||||
|
if (err) {
|
||||||
console.error('[loader] Error during startup');
|
console.error('[loader] Error during startup');
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,57 @@
|
|||||||
{
|
{
|
||||||
"extends": "nodebb/public"
|
"globals": {
|
||||||
|
"app": true,
|
||||||
|
"io": true,
|
||||||
|
"socket": true,
|
||||||
|
"ajaxify": true,
|
||||||
|
"config": true,
|
||||||
|
"RELATIVE_PATH": true,
|
||||||
|
"utils": true,
|
||||||
|
"overrides": true,
|
||||||
|
"componentHandler": true,
|
||||||
|
"bootbox": true,
|
||||||
|
"Visibility": true,
|
||||||
|
"Tinycon": true,
|
||||||
|
"Promise": true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"jquery": true,
|
||||||
|
"amd": true,
|
||||||
|
"browser": true,
|
||||||
|
"es6": false
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-dupe-class-members": "off",
|
||||||
|
"no-var": "off",
|
||||||
|
"object-shorthand": "off",
|
||||||
|
"prefer-arrow-callback": "off",
|
||||||
|
"prefer-spread": "off",
|
||||||
|
"prefer-reflect": "off",
|
||||||
|
"prefer-template": "off"
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 5,
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"arrowFunctions": false,
|
||||||
|
"classes": false,
|
||||||
|
"defaultParams": false,
|
||||||
|
"destructuring": 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,
|
||||||
|
"spread": false,
|
||||||
|
"superInFunctions": false,
|
||||||
|
"templateStrings": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
public/.jshintrc
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
{
|
||||||
|
"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,
|
||||||
|
"RELATIVE_PATH": 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
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Excessive Load Warning</title>
|
<title>Excessive Load Warning</title>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Ubuntu:400,500,700' rel='stylesheet' type='text/css'>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
background: #00A9EA;
|
background: #00A9EA;
|
||||||
color: white;
|
color: white;
|
||||||
/* see public/less/admin/vars.less for documentation on system font family */
|
font-family: 'Ubuntu', sans-serif;
|
||||||
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;
|
text-align: center;
|
||||||
-webkit-transform-style: preserve-3d;
|
-webkit-transform-style: preserve-3d;
|
||||||
-moz-transform-style: preserve-3d;
|
-moz-transform-style: preserve-3d;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 5.9 KiB |
@@ -1,16 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="321" height="75" viewBox="0 0 321 75">
|
|
||||||
<defs>
|
|
||||||
<radialGradient id="nodebb-a" cx="65.599%" cy="0%" r="169.036%" fx="65.599%" fy="0%" gradientTransform="matrix(-.5183 .5916 -.38031 -.80624 .996 -.388)">
|
|
||||||
<stop offset="0%" stop-color="#2A6CBE"/>
|
|
||||||
<stop offset="38.688%" stop-color="#2062BC"/>
|
|
||||||
<stop offset="49.182%" stop-color="#1F5FBC"/>
|
|
||||||
<stop offset="66.583%" stop-color="#1C5ABD"/>
|
|
||||||
<stop offset="85.354%" stop-color="#1956BC"/>
|
|
||||||
<stop offset="100%" stop-color="#1851BE"/>
|
|
||||||
</radialGradient>
|
|
||||||
</defs>
|
|
||||||
<g fill="none" transform="translate(1 1)">
|
|
||||||
<path fill="#000306" stroke="#000306" stroke-width=".275" d="M195.810017,20 C210.691849,20 221.256813,28.7272272 221.484017,45.845679 C221.490864,46.3615394 221.461776,47.1194739 221.396754,48.1194827 C221.328352,49.1714504 220.455158,49.9897119 219.400969,49.9897119 L179.110557,49.9897119 C179.110557,56.6336943 182.723978,64.2757202 196.378026,64.2757202 C204.088827,64.2757202 211.625406,61.928339 218.987763,57.2335766 L219.553745,56.8677968 C220.246813,56.4139645 221.17656,56.6079034 221.630392,57.3009716 C221.757029,57.4943637 221.837254,57.7144077 221.864806,57.943925 C222.131013,60.1615294 222.004084,61.5832211 221.484017,62.2089999 C220.452051,63.4507301 210.901843,73 196.378026,73 C180.58738,73 169,61.8765432 169,46.3909465 C169,31.3415638 180.019372,20 195.810017,20 Z M162.92733,0 C164.031899,-4.2495073e-16 164.92733,0.8954305 164.92733,2 L164.928075,44.1266361 C164.975781,44.8118124 165,45.5058194 165,46.2079256 C165,61.5334332 153.460581,73 138,73 C122.427386,73 111,61.5334332 111,46.2079256 C111,30.882418 122.427386,19.4158511 138,19.4158511 C144.981278,19.4158511 151.163029,21.7538895 155.843826,25.7295173 L155.843557,4.54188628 C155.843557,2.03347175 157.877029,4.60788274e-16 160.385444,0 L162.92733,0 Z M81,20 C96.4605809,20 108,31.3415638 108,46.5 C108,61.6584362 96.4605809,73 81,73 C65.4273859,73 54,61.6584362 54,46.5 C54,31.3415638 65.4273859,20 81,20 Z M27.324263,20 C41.6099773,20 50,29.1649049 50,41.7801268 L50,67.5 C50,69.4329966 48.4329966,71 46.5,71 L42.2494331,71 C41.1448636,71 40.2494331,70.1045695 40.2494331,69 L40.2494331,42.5348837 C40.2494331,34.3403805 35.8276644,28.6257928 26.3038549,28.6257928 C10.0816327,28.6257928 9.75718821,35.7795705 9.75069932,44.6831843 L9.75056689,71 L2,71 C0.8954305,71 1.3527075e-16,70.1045695 0,69 L0,35.2932975 L0,35.2932975 C0,24.3935718 19.1609977,20 27.324263,20 Z M81,28.7242798 C70.8049793,28.7242798 63.6348548,36.4670782 63.6348548,46.5 C63.6348548,56.3148148 70.8049793,64.2757202 81,64.2757202 C91.1950207,64.2757202 98.3651452,56.3148148 98.3651452,46.5 C98.3651452,36.4670782 91.1950207,28.7242798 81,28.7242798 Z M138,28.2362872 C127.804979,28.2362872 120.634855,36.0644241 120.634855,46.2079256 C120.634855,56.1309161 127.804979,64.179564 138,64.179564 C148.195021,64.179564 155.365145,56.1309161 155.365145,46.2079256 C155.365145,36.0644241 148.195021,28.2362872 138,28.2362872 Z M195.810017,28.7242798 C186.721876,28.7242798 180.473779,33.9588477 179.224159,41.8106996 L211.259858,41.8106996 C210.010238,33.9588477 204.443752,28.7242798 195.810017,28.7242798 Z"/>
|
|
||||||
<path fill="url(#nodebb-a)" d="M277,19 L276.999615,57.7303365 C276.99251,64.180962 276.88949,68.6242617 276.88949,73 L276.88949,73 L255.649055,73 C242.962262,73 236,67.06 236,57.7257143 C236,51.4771429 239.558488,46.9257143 245.1283,45.0742857 C240.564149,43.1457143 237.779243,38.8257143 237.779243,33.5028571 C237.779243,24.8628571 244.664149,19 256.732074,19 L256.732074,19 L277,19 Z M299.267926,19 C311.335851,19 318.220757,24.8628571 318.220757,33.5028571 C318.220757,38.8257143 315.435851,43.1457143 310.8717,45.0742857 C316.441512,46.9257143 320,51.4771429 320,57.7257143 C320,67.06 313.037738,73 300.350945,73 L279.11051,73 L279.11051,73 C279.11051,68.6242617 279.00749,64.180962 279.000385,57.7303365 L279,19 L299.267926,19 Z M266.092452,49.8571429 L256.499999,49.8571429 C250.156602,49.8571429 246.984904,52.2485714 246.984904,56.9542857 C246.984904,61.8914286 249.924527,64.36 255.726414,64.36 L255.726414,64.36 L260.754716,64.36 C264.777358,64.36 266.092452,62.4314286 266.092452,56.5685714 L266.092452,56.5685714 L266.092452,49.8571429 Z M299.500001,49.8571429 L289.907548,49.8571429 L289.907548,56.5685714 C289.907548,62.4314286 291.222642,64.36 295.245284,64.36 L300.273586,64.36 C306.075473,64.36 309.015096,61.8914286 309.015096,56.9542857 C309.015096,52.2485714 305.843398,49.8571429 299.500001,49.8571429 Z M266.169811,27.64 L257.350942,27.64 C251.703772,27.64 248.764149,30.1857143 248.764149,34.5057143 C248.764149,38.8257143 251.703772,41.3714286 257.350942,41.3714286 L257.350942,41.3714286 L266.169811,41.3714286 L266.169811,27.64 Z M298.649058,27.64 L289.830189,27.64 L289.830189,41.3714286 L298.649058,41.3714286 C304.296228,41.3714286 307.235851,38.8257143 307.235851,34.5057143 C307.235851,30.1857143 304.296228,27.64 298.649058,27.64 Z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
3
public/js-enabled.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/*
|
||||||
|
The following stylesheet is only included on pages that can execute javascript
|
||||||
|
*/
|
||||||
@@ -3,9 +3,5 @@
|
|||||||
"alert.confirm-restart": "هل تريد بالتأكيد إعادة تشغيل NodeBB؟",
|
"alert.confirm-restart": "هل تريد بالتأكيد إعادة تشغيل NodeBB؟",
|
||||||
|
|
||||||
"acp-title": "لوحة تحكم إدارة NodeBB | %1",
|
"acp-title": "لوحة تحكم إدارة NodeBB | %1",
|
||||||
"settings-header-contents": "محتويات",
|
"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",
|
|
||||||
"changes-not-saved-message": "NodeBB encountered a problem saving your changes. (%1)"
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
{
|
{
|
||||||
"post-cache": "التخزين المؤقت للمشاركات",
|
"post-cache": "التخزين المؤقت للمشاركات",
|
||||||
|
"posts-in-cache": "المشاركات المخزنة مؤقتاً",
|
||||||
|
"average-post-size": "متوسط حجم المشاركة",
|
||||||
|
"length-to-max": "الطول / أقصى حد",
|
||||||
"percent-full": "1% كاملة",
|
"percent-full": "1% كاملة",
|
||||||
"post-cache-size": "حجم التخزين المؤقت للمشاركات",
|
"post-cache-size": "حجم التخزين المؤقت للمشاركات",
|
||||||
"items-in-cache": "العناصر في التخزين المؤقت"
|
"items-in-cache": "العناصر في التخزين المؤقت",
|
||||||
|
"control-panel": "لوحة التحكم",
|
||||||
|
"update-settings": "تحديث إعدادات التخزين المؤقت"
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,10 @@
|
|||||||
"events": "أحداث",
|
"events": "أحداث",
|
||||||
"no-events": "لا توجد أحداث",
|
"no-events": "لا توجد أحداث",
|
||||||
"control-panel": "لوحة تحكم الأحداث",
|
"control-panel": "لوحة تحكم الأحداث",
|
||||||
"delete-events": "حذف الاحداث",
|
"filters": "Filters",
|
||||||
"confirm-delete-all-events": "Are you sure you want to delete all logged events?",
|
"filters-apply": "Apply Filters",
|
||||||
"filters": "تصفية",
|
"filter-type": "Event Type",
|
||||||
"filters-apply": "تطبيق التصفية",
|
"filter-start": "Start Date",
|
||||||
"filter-type": "نوع الحدث",
|
"filter-end": "End Date",
|
||||||
"filter-start": "تاريخ البدء",
|
"filter-perPage": "Per Page"
|
||||||
"filter-end": "تاريخ الانتهاء",
|
|
||||||
"filter-perPage": "لكل صفحة"
|
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,12 @@
|
|||||||
{
|
{
|
||||||
"you-are-on": "You are on <strong>%1:%2</strong>",
|
"you-are-on": "Info - You are on <strong>%1:%2</strong>",
|
||||||
"ip": "IP <strong>%1</strong>",
|
|
||||||
"nodes-responded": "%1 nodes responded within %2ms!",
|
"nodes-responded": "%1 nodes responded within %2ms!",
|
||||||
"host": "host",
|
"host": "host",
|
||||||
"primary": "primary / run jobs",
|
|
||||||
"pid": "pid",
|
"pid": "pid",
|
||||||
"nodejs": "nodejs",
|
"nodejs": "nodejs",
|
||||||
"online": "online",
|
"online": "online",
|
||||||
"git": "git",
|
"git": "git",
|
||||||
"process-memory": "process memory",
|
"memory": "memory",
|
||||||
"system-memory": "system memory",
|
|
||||||
"used-memory-process": "Used memory by process",
|
|
||||||
"used-memory-os": "Used system memory",
|
|
||||||
"total-memory-os": "Total system memory",
|
|
||||||
"load": "system load",
|
"load": "system load",
|
||||||
"cpu-usage": "cpu usage",
|
"cpu-usage": "cpu usage",
|
||||||
"uptime": "uptime",
|
"uptime": "uptime",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"trending": "Trending",
|
|
||||||
"installed": "منصبة",
|
"installed": "منصبة",
|
||||||
"active": "مفعلة",
|
"active": "مفعلة",
|
||||||
"inactive": "معطلة",
|
"inactive": "معطلة",
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
"alert.upgraded": "الإضافة مرقاة",
|
"alert.upgraded": "الإضافة مرقاة",
|
||||||
"alert.installed": "الإضافة منصبة",
|
"alert.installed": "الإضافة منصبة",
|
||||||
"alert.uninstalled": "تم إلغاء تنصيب الإضافة",
|
"alert.uninstalled": "تم إلغاء تنصيب الإضافة",
|
||||||
"alert.activate-success": "Please rebuild and restart your NodeBB to fully activate this plugin",
|
"alert.activate-success": "يرجى إعادة تشغيل NodeBB لتنشيط الإضافة بشكل بالكامل",
|
||||||
"alert.deactivate-success": "تم تعطيل الإضافة بنجاح",
|
"alert.deactivate-success": "تم تعطيل الإضافة بنجاح",
|
||||||
"alert.upgrade-success": "Please rebuild and restart your NodeBB to fully upgrade this plugin.",
|
"alert.upgrade-success": "Please rebuild and restart your NodeBB to fully upgrade this plugin.",
|
||||||
"alert.install-success": "تم تثبيت الإضافة بنجاح، يرجى تفعيلها.",
|
"alert.install-success": "تم تثبيت الإضافة بنجاح، يرجى تفعيلها.",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
|
"control-panel": "Rewards Control",
|
||||||
|
"new-reward": "New Reward",
|
||||||
|
|
||||||
"alert.delete-success": "Successfully deleted reward",
|
"alert.delete-success": "Successfully deleted reward",
|
||||||
"alert.no-inputs-found": "Illegal reward - no inputs found!",
|
"alert.no-inputs-found": "Illegal reward - no inputs found!",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"available": "Available 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.",
|
"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.",
|
"none-installed": "No widgets found! Activate the essential widgets plugin in the <a href=\"%1\">plugins</a> control panel.",
|
||||||
"clone-from": "Clone widgets from",
|
"clone-from": "Clone widgets from",
|
||||||
"containers.available": "Available Containers",
|
"containers.available": "Available Containers",
|
||||||
"containers.explanation": "Drag and drop on top of any active widget",
|
"containers.explanation": "Drag and drop on top of any active widget",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"forum-traffic": "Forum Traffic",
|
"forum-traffic": "Forum Traffic",
|
||||||
"page-views": "مشاهدات الصفحات",
|
"page-views": "مشاهدات الصفحات",
|
||||||
"unique-visitors": "زائرين فريدين",
|
"unique-visitors": "زائرين فريدين",
|
||||||
"logins": "Logins",
|
|
||||||
"new-users": "New Users",
|
"new-users": "New Users",
|
||||||
"posts": "مشاركات",
|
"posts": "مشاركات",
|
||||||
"topics": "مواضيع",
|
"topics": "مواضيع",
|
||||||
@@ -30,7 +29,6 @@
|
|||||||
"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>",
|
"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-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>",
|
"prerelease-warning": "<p>هذه نسخة <strong>ماقبل الإصدار</strong> من NodeBB. قد تحدث أخطاء غير مقصودة. <i class=\"fa fa-exclamation-triangle\"></i></p>",
|
||||||
"fallback-emailer-not-found": "Fallback emailer not found!",
|
|
||||||
"running-in-development": "المنتدى قيد التشغيل في وضع \"المطورين\". وقد تكون هناك ثغرات أمنية مفتوحة؛ من فضلك تواصل مع مسؤول نظامك.",
|
"running-in-development": "المنتدى قيد التشغيل في وضع \"المطورين\". وقد تكون هناك ثغرات أمنية مفتوحة؛ من فضلك تواصل مع مسؤول نظامك.",
|
||||||
"latest-lookup-failed": "<p>Failed to look up latest available version of NodeBB</p>",
|
"latest-lookup-failed": "<p>Failed to look up latest available version of NodeBB</p>",
|
||||||
|
|
||||||
@@ -56,8 +54,8 @@
|
|||||||
"active-users.total": "المجموع",
|
"active-users.total": "المجموع",
|
||||||
"active-users.connections": "Connections",
|
"active-users.connections": "Connections",
|
||||||
|
|
||||||
"guest-registered-users": "Guest vs Registered Users",
|
"anonymous-registered-users": "المجهولين مقابل المستخدمين المسجلين",
|
||||||
"guest": "Guest",
|
"anonymous": "مجهول",
|
||||||
"registered": "مسجل",
|
"registered": "مسجل",
|
||||||
|
|
||||||
"user-presence": "تواجد المستخدمين",
|
"user-presence": "تواجد المستخدمين",
|
||||||
@@ -68,7 +66,6 @@
|
|||||||
"unread": "غير مقروء",
|
"unread": "غير مقروء",
|
||||||
|
|
||||||
"high-presence-topics": "مواضيع ذات حضور قوي",
|
"high-presence-topics": "مواضيع ذات حضور قوي",
|
||||||
"popular-searches": "Popular Searches",
|
|
||||||
|
|
||||||
"graphs.page-views": "مشاهدات الصفحة",
|
"graphs.page-views": "مشاهدات الصفحة",
|
||||||
"graphs.page-views-registered": "Page Views Registered",
|
"graphs.page-views-registered": "Page Views Registered",
|
||||||
@@ -76,15 +73,7 @@
|
|||||||
"graphs.page-views-bot": "Page Views Bot",
|
"graphs.page-views-bot": "Page Views Bot",
|
||||||
"graphs.unique-visitors": "زوار فريدين",
|
"graphs.unique-visitors": "زوار فريدين",
|
||||||
"graphs.registered-users": "مستخدمين مسجلين",
|
"graphs.registered-users": "مستخدمين مسجلين",
|
||||||
"graphs.guest-users": "Guest Users",
|
"graphs.anonymous-users": "مستخدمين مجهولين",
|
||||||
"last-restarted-by": "Last restarted by",
|
"last-restarted-by": "Last restarted by",
|
||||||
"no-users-browsing": "No users browsing",
|
"no-users-browsing": "No users browsing"
|
||||||
|
|
||||||
"back-to-dashboard": "Back to Dashboard",
|
|
||||||
"details.no-users": "No users have joined within the selected timeframe",
|
|
||||||
"details.no-topics": "No topics have been posted within the selected timeframe",
|
|
||||||
"details.no-searches": "No searches have been made yet",
|
|
||||||
"details.no-logins": "No logins have been recorded within the selected timeframe",
|
|
||||||
"details.logins-static": "NodeBB only saves session data for %1 days, and so this table below will only show the most recently active sessions",
|
|
||||||
"details.logins-login-time": "Login Time"
|
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,6 @@
|
|||||||
"properties": "Properties:",
|
"properties": "Properties:",
|
||||||
"groups": "Groups:",
|
"groups": "Groups:",
|
||||||
"open-new-window": "Open in a new window",
|
"open-new-window": "Open in a new window",
|
||||||
"dropdown": "Dropdown",
|
|
||||||
"dropdown-placeholder": "Place your dropdown menu items below, ie: <br/><li><a href="https://myforum.com">Link 1</a></li>",
|
|
||||||
|
|
||||||
"btn.delete": "Delete",
|
"btn.delete": "Delete",
|
||||||
"btn.disable": "Disable",
|
"btn.disable": "Disable",
|
||||||
@@ -10,16 +10,12 @@
|
|||||||
"custom-class": "Custom Class",
|
"custom-class": "Custom Class",
|
||||||
"num-recent-replies": "# of Recent Replies",
|
"num-recent-replies": "# of Recent Replies",
|
||||||
"ext-link": "External Link",
|
"ext-link": "External Link",
|
||||||
"subcategories-per-page": "Subcategories per page",
|
|
||||||
"is-section": "Treat this category as a section",
|
"is-section": "Treat this category as a section",
|
||||||
"post-queue": "Post queue",
|
|
||||||
"tag-whitelist": "Tag Whitelist",
|
|
||||||
"upload-image": "Upload Image",
|
"upload-image": "Upload Image",
|
||||||
"delete-image": "Remove",
|
"delete-image": "Remove",
|
||||||
"category-image": "Category Image",
|
"category-image": "Category Image",
|
||||||
"parent-category": "Parent Category",
|
"parent-category": "Parent Category",
|
||||||
"optional-parent-category": "(Optional) Parent Category",
|
"optional-parent-category": "(Optional) Parent Category",
|
||||||
"top-level": "Top Level",
|
|
||||||
"parent-category-none": "(None)",
|
"parent-category-none": "(None)",
|
||||||
"copy-parent": "Copy Parent",
|
"copy-parent": "Copy Parent",
|
||||||
"copy-settings": "Copy Settings From",
|
"copy-settings": "Copy Settings From",
|
||||||
@@ -30,10 +26,6 @@
|
|||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
"edit": "Edit",
|
"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",
|
"select-category": "Select Category",
|
||||||
"set-parent-category": "Set Parent Category",
|
"set-parent-category": "Set Parent Category",
|
||||||
@@ -50,8 +42,6 @@
|
|||||||
"privileges.no-users": "No user-specific privileges in this category.",
|
"privileges.no-users": "No user-specific privileges in this category.",
|
||||||
"privileges.section-group": "Group",
|
"privileges.section-group": "Group",
|
||||||
"privileges.group-private": "This group is private",
|
"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.search-group": "Add Group",
|
||||||
"privileges.copy-to-children": "Copy to Children",
|
"privileges.copy-to-children": "Copy to Children",
|
||||||
"privileges.copy-from-category": "Copy from Category",
|
"privileges.copy-from-category": "Copy from Category",
|
||||||
@@ -73,6 +63,7 @@
|
|||||||
"alert.create-success": "Category successfully created!",
|
"alert.create-success": "Category successfully created!",
|
||||||
"alert.none-active": "You have no active categories.",
|
"alert.none-active": "You have no active categories.",
|
||||||
"alert.create": "Create a Category",
|
"alert.create": "Create a Category",
|
||||||
|
"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-purge": "<p class=\"lead\">Do you really want to purge this category \"%1\"?</p><h5><strong class=\"text-danger\">Warning!</strong> All topics and posts in this category will be purged!</h5> <p class=\"help-block\">Purging a category will remove all topics and posts, and delete the category from the database. If you want to remove a category <em>temporarily</em>, you'll want to \"disable\" the category instead.</p>",
|
"alert.confirm-purge": "<p class=\"lead\">Do you really want to purge this category \"%1\"?</p><h5><strong class=\"text-danger\">Warning!</strong> All topics and posts in this category will be purged!</h5> <p class=\"help-block\">Purging a category will remove all topics and posts, and delete the category from the database. If you want to remove a category <em>temporarily</em>, you'll want to \"disable\" the category instead.</p>",
|
||||||
"alert.purge-success": "Category purged!",
|
"alert.purge-success": "Category purged!",
|
||||||
"alert.copy-success": "Settings Copied!",
|
"alert.copy-success": "Settings Copied!",
|
||||||
@@ -84,9 +75,7 @@
|
|||||||
"alert.user-search": "Search for a user here...",
|
"alert.user-search": "Search for a user here...",
|
||||||
"alert.find-group": "Find a Group",
|
"alert.find-group": "Find a Group",
|
||||||
"alert.group-search": "Search for a group here...",
|
"alert.group-search": "Search for a group here...",
|
||||||
"alert.not-enough-whitelisted-tags": "Whitelisted tags are less than minimum tags, you need to create more whitelisted tags!",
|
|
||||||
"collapse-all": "Collapse All",
|
"collapse-all": "Collapse All",
|
||||||
"expand-all": "Expand All",
|
"expand-all": "Expand All",
|
||||||
"disable-on-create": "Disable on create",
|
"disable-on-create": "Disable on create"
|
||||||
"no-matches": "No matches"
|
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,10 @@
|
|||||||
"default": "System default",
|
"default": "System default",
|
||||||
"default-help": "<em>System default</em> means the user has not explicitly overridden the global forum setting for digests, which is currently: "<strong>%1</strong>"",
|
"default-help": "<em>System default</em> means the user has not explicitly overridden the global forum setting for digests, which is currently: "<strong>%1</strong>"",
|
||||||
"resend": "Resend Digest",
|
"resend": "Resend Digest",
|
||||||
"resend-all-confirm": "Are you sure you wish to manually execute this digest run?",
|
"resend-all-confirm": "Are you sure you wish to mnually execute this digest run?",
|
||||||
"resent-single": "Manual digest resend completed",
|
"resent-single": "Manual digest resend completed",
|
||||||
"resent-day": "Daily digest resent",
|
"resent-day": "Daily digest resent",
|
||||||
"resent-week": "Weekly digest resent",
|
"resent-week": "Weekly digest resent",
|
||||||
"resent-biweek": "Bi-Weekly digest resent",
|
|
||||||
"resent-month": "Monthly digest resent",
|
"resent-month": "Monthly digest resent",
|
||||||
"null": "<em>Never</em>",
|
"null": "<em>Never</em>",
|
||||||
"manual-run": "Manual digest run:",
|
"manual-run": "Manual digest run:",
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
"hidden": "Hidden",
|
"hidden": "Hidden",
|
||||||
"private": "Private",
|
"private": "Private",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
|
||||||
"privileges": "Privileges",
|
|
||||||
"download-csv": "CSV",
|
|
||||||
"search-placeholder": "Search",
|
"search-placeholder": "Search",
|
||||||
"create": "Create Group",
|
"create": "Create Group",
|
||||||
"description-placeholder": "A short description about your group",
|
"description-placeholder": "A short description about your group",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"post-queue": "Post Queue",
|
"post-queue": "Post Queue",
|
||||||
"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>.",
|
"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>.",
|
||||||
@@ -8,14 +7,5 @@
|
|||||||
"content": "Content",
|
"content": "Content",
|
||||||
"posted": "Posted",
|
"posted": "Posted",
|
||||||
"reply-to": "Reply to \"%1\"",
|
"reply-to": "Reply to \"%1\"",
|
||||||
"content-editable": "Click on content to edit",
|
"content-editable": "You can click on individual content to edit before posting."
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
{
|
{
|
||||||
"global": "Global",
|
"global": "Global",
|
||||||
"admin": "Admin",
|
"global.no-users": "No user-specific global privileges.",
|
||||||
"group-privileges": "Group Privileges",
|
"group-privileges": "Group Privileges",
|
||||||
"user-privileges": "User Privileges",
|
"user-privileges": "User Privileges",
|
||||||
"edit-privileges": "Edit Privileges",
|
|
||||||
"select-clear-all": "Select/Clear All",
|
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"upload-images": "Upload Images",
|
"upload-images": "Upload Images",
|
||||||
"upload-files": "Upload Files",
|
"upload-files": "Upload Files",
|
||||||
"signature": "Signature",
|
"signature": "Signature",
|
||||||
"ban": "Ban",
|
"ban": "Ban",
|
||||||
"invite": "Invite",
|
|
||||||
"search-content": "Search Content",
|
"search-content": "Search Content",
|
||||||
"search-users": "Search Users",
|
"search-users": "Search Users",
|
||||||
"search-tags": "Search Tags",
|
"search-tags": "Search Tags",
|
||||||
@@ -25,7 +22,6 @@
|
|||||||
"access-topics": "Access Topics",
|
"access-topics": "Access Topics",
|
||||||
"create-topics": "Create Topics",
|
"create-topics": "Create Topics",
|
||||||
"reply-to-topics": "Reply to Topics",
|
"reply-to-topics": "Reply to Topics",
|
||||||
"schedule-topics": "Schedule Topics",
|
|
||||||
"tag-topics": "Tag Topics",
|
"tag-topics": "Tag Topics",
|
||||||
"edit-posts": "Edit Posts",
|
"edit-posts": "Edit Posts",
|
||||||
"view-edit-history": "View Edit History",
|
"view-edit-history": "View Edit History",
|
||||||
@@ -35,29 +31,5 @@
|
|||||||
"downvote-posts": "Downvote Posts",
|
"downvote-posts": "Downvote Posts",
|
||||||
"delete-topics": "Delete Topics",
|
"delete-topics": "Delete Topics",
|
||||||
"purge": "Purge",
|
"purge": "Purge",
|
||||||
"moderate": "Moderate",
|
"moderate": "Moderate"
|
||||||
"admin-dashboard": "Dashboard",
|
|
||||||
"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.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."
|
|
||||||
}
|
}
|
||||||
@@ -2,17 +2,18 @@
|
|||||||
"none": "Your forum does not have any topics with tags yet.",
|
"none": "Your forum does not have any topics with tags yet.",
|
||||||
"bg-color": "Background Colour",
|
"bg-color": "Background Colour",
|
||||||
"text-color": "Text Colour",
|
"text-color": "Text Colour",
|
||||||
"description": "Select tags by clicking or dragging, use <code>CTRL</code> to select multiple tags.",
|
"create-modify": "Create & Modify Tags",
|
||||||
|
"description": "Select tags via clicking and/or dragging, use shift to select multiple.",
|
||||||
"create": "Create Tag",
|
"create": "Create Tag",
|
||||||
"modify": "Modify Tags",
|
"modify": "Modify Tags",
|
||||||
"rename": "Rename Tags",
|
"rename": "Rename Tags",
|
||||||
"delete": "Delete Selected Tags",
|
"delete": "Delete Selected Tags",
|
||||||
"search": "Search for tags...",
|
"search": "Search for tags...",
|
||||||
"settings": "Tags Settings",
|
"settings": "Click <a href=\"%1\">here</a> to visit the tag settings page.",
|
||||||
"name": "Tag Name",
|
"name": "Tag Name",
|
||||||
|
|
||||||
"alerts.editing": "Editing tag(s)",
|
"alerts.editing-multiple": "Editing multiple tags",
|
||||||
|
"alerts.editing-x": "Editing \"%1\" tag",
|
||||||
"alerts.confirm-delete": "Do you want to delete the selected tags?",
|
"alerts.confirm-delete": "Do you want to delete the selected tags?",
|
||||||
"alerts.update-success": "Tag Updated!",
|
"alerts.update-success": "Tag Updated!"
|
||||||
"reset-colors": "Reset colors"
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,5 @@
|
|||||||
"orphaned": "Orphaned",
|
"orphaned": "Orphaned",
|
||||||
"size/filecount": "Size / Filecount",
|
"size/filecount": "Size / Filecount",
|
||||||
"confirm-delete": "Do you really want to delete this file?",
|
"confirm-delete": "Do you really want to delete this file?",
|
||||||
"filecount": "%1 files",
|
"filecount": "%1 files"
|
||||||
"new-folder": "New Folder",
|
|
||||||
"name-new-folder": "Enter a name for new the folder"
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"users": "المستخدمين",
|
"users": "المستخدمين",
|
||||||
"edit": "Actions",
|
"edit": "تحرير",
|
||||||
"make-admin": "Make Admin",
|
"make-admin": "Make Admin",
|
||||||
"remove-admin": "Remove Admin",
|
"remove-admin": "Remove Admin",
|
||||||
"validate-email": "Validate Email",
|
"validate-email": "Validate Email",
|
||||||
@@ -12,18 +12,23 @@
|
|||||||
"unban": "Unban User(s)",
|
"unban": "Unban User(s)",
|
||||||
"reset-lockout": "Reset Lockout",
|
"reset-lockout": "Reset Lockout",
|
||||||
"reset-flags": "Reset Flags",
|
"reset-flags": "Reset Flags",
|
||||||
"delete": "Delete <strong>User(s)</strong>",
|
"delete": "Delete User(s)",
|
||||||
"delete-content": "Delete User(s) <strong>Content</strong>",
|
"purge": "Delete User(s) and Content",
|
||||||
"purge": "Delete <strong>User(s)</strong> and <strong>Content</strong>",
|
|
||||||
"download-csv": "Download CSV",
|
"download-csv": "Download CSV",
|
||||||
"manage-groups": "Manage Groups",
|
"manage-groups": "Manage Groups",
|
||||||
"add-group": "Add Group",
|
"add-group": "Add Group",
|
||||||
"invite": "Invite",
|
"invite": "Invite",
|
||||||
"new": "New User",
|
"new": "New User",
|
||||||
"filter-by": "Filter by",
|
|
||||||
|
"pills.latest": "Latest Users",
|
||||||
"pills.unvalidated": "Not Validated",
|
"pills.unvalidated": "Not Validated",
|
||||||
"pills.validated": "Validated",
|
"pills.no-posts": "No Posts",
|
||||||
|
"pills.top-posters": "Top Posters",
|
||||||
|
"pills.top-rep": "Most Reputation",
|
||||||
|
"pills.inactive": "Inactive",
|
||||||
|
"pills.flagged": "Most Flagged",
|
||||||
"pills.banned": "Banned",
|
"pills.banned": "Banned",
|
||||||
|
"pills.search": "User Search",
|
||||||
|
|
||||||
"50-per-page": "50 per page",
|
"50-per-page": "50 per page",
|
||||||
"100-per-page": "100 per page",
|
"100-per-page": "100 per page",
|
||||||
@@ -47,8 +52,6 @@
|
|||||||
"users.uid": "uid",
|
"users.uid": "uid",
|
||||||
"users.username": "username",
|
"users.username": "username",
|
||||||
"users.email": "email",
|
"users.email": "email",
|
||||||
"users.no-email": "(no email)",
|
|
||||||
"users.ip": "IP",
|
|
||||||
"users.postcount": "postcount",
|
"users.postcount": "postcount",
|
||||||
"users.reputation": "reputation",
|
"users.reputation": "reputation",
|
||||||
"users.flags": "flags",
|
"users.flags": "flags",
|
||||||
@@ -90,11 +93,9 @@
|
|||||||
"alerts.validate-email-success": "Emails validated",
|
"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.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-confirm": "Do you want to send password reset email(s) to these user(s)?",
|
||||||
"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.confirm-delete": "<b>Warning!</b><br/>Do you really want to delete user(s)?<br/> This action is not reversable! Only the user account will be deleted, their posts and topics will remain.",
|
||||||
"alerts.delete-success": "User(s) Deleted!",
|
"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>",
|
"alerts.confirm-purge": "<b>Warning!</b><br/>Do you really want to delete user(s) and their content?<br/> This action is not reversable! All user data and content will be erased!",
|
||||||
"alerts.delete-content-success": "User(s) Content Deleted!",
|
|
||||||
"alerts.confirm-purge": "<strong>Warning!</strong><p>Do you really want to delete <strong>user(s) and their content</strong>?</p><p>This action is not reversible! All user data and content will be erased!</p>",
|
|
||||||
"alerts.create": "Create User",
|
"alerts.create": "Create User",
|
||||||
"alerts.button-create": "Create",
|
"alerts.button-create": "Create",
|
||||||
"alerts.button-cancel": "Cancel",
|
"alerts.button-cancel": "Cancel",
|
||||||
@@ -104,7 +105,5 @@
|
|||||||
|
|
||||||
"alerts.prompt-email": "Emails: ",
|
"alerts.prompt-email": "Emails: ",
|
||||||
"alerts.email-sent-to": "An invitation email has been sent to %1",
|
"alerts.email-sent-to": "An invitation email has been sent to %1",
|
||||||
"alerts.x-users-found": "%1 user(s) found, (%2 seconds)",
|
"alerts.x-users-found": "%1 user(s) found! Search took %2 ms."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"section-dashboard": "Dashboards",
|
|
||||||
"dashboard/overview": "Overview",
|
|
||||||
"dashboard/logins": "Logins",
|
|
||||||
"dashboard/users": "Users",
|
|
||||||
"dashboard/topics": "Topics",
|
|
||||||
"dashboard/searches": "Searches",
|
|
||||||
"section-general": "عام",
|
"section-general": "عام",
|
||||||
|
"general/dashboard": "اللوحة الرئيسية",
|
||||||
|
"general/homepage": "الصفحة الرئيسية",
|
||||||
|
"general/navigation": "التصفح",
|
||||||
|
"general/languages": "اللغات",
|
||||||
|
"general/sounds": "الأصوات",
|
||||||
|
"general/social": "شبكات التواصل",
|
||||||
|
|
||||||
"section-manage": "إدارة",
|
"section-manage": "إدارة",
|
||||||
"manage/categories": "الأقسام",
|
"manage/categories": "الأقسام",
|
||||||
@@ -22,23 +22,17 @@
|
|||||||
|
|
||||||
"section-settings": "إعدادات",
|
"section-settings": "إعدادات",
|
||||||
"settings/general": "عامة",
|
"settings/general": "عامة",
|
||||||
"settings/homepage": "Home Page",
|
"settings/reputation": "السمعة",
|
||||||
"settings/navigation": "Navigation",
|
|
||||||
"settings/reputation": "Reputation & Flags",
|
|
||||||
"settings/email": "البريد الإلكتروني",
|
"settings/email": "البريد الإلكتروني",
|
||||||
"settings/user": "Users",
|
"settings/user": "الأعضاء",
|
||||||
"settings/group": "Groups",
|
"settings/group": "المجموعات",
|
||||||
"settings/guest": "الزوار",
|
"settings/guest": "الزوار",
|
||||||
"settings/uploads": "الرفع",
|
"settings/uploads": "الرفع",
|
||||||
"settings/languages": "Languages",
|
"settings/post": "المشاركة",
|
||||||
"settings/post": "Posts",
|
"settings/chat": "الدردشة",
|
||||||
"settings/chat": "Chats",
|
|
||||||
"settings/pagination": "ترقيم الصفحات",
|
"settings/pagination": "ترقيم الصفحات",
|
||||||
"settings/tags": "الكلمات المفتاحية",
|
"settings/tags": "الكلمات المفتاحية",
|
||||||
"settings/notifications": "التنبيهات",
|
"settings/notifications": "التنبيهات",
|
||||||
"settings/api": "API Access",
|
|
||||||
"settings/sounds": "Sounds",
|
|
||||||
"settings/social": "Social",
|
|
||||||
"settings/cookies": "Cookies",
|
"settings/cookies": "Cookies",
|
||||||
"settings/web-crawler": "Web Crawler",
|
"settings/web-crawler": "Web Crawler",
|
||||||
"settings/sockets": "Sockets",
|
"settings/sockets": "Sockets",
|
||||||
@@ -76,7 +70,7 @@
|
|||||||
"logout": "Log out",
|
"logout": "Log out",
|
||||||
"view-forum": "View Forum",
|
"view-forum": "View Forum",
|
||||||
|
|
||||||
"search.placeholder": "Press "/" to search for settings",
|
"search.placeholder": "Search for settings",
|
||||||
"search.no-results": "No results...",
|
"search.no-results": "No results...",
|
||||||
"search.search-forum": "Search the forum for <strong></strong>",
|
"search.search-forum": "Search the forum for <strong></strong>",
|
||||||
"search.keep-typing": "Type more to see results...",
|
"search.keep-typing": "Type more to see results...",
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
"maintenance-mode.message": "Maintenance Message",
|
"maintenance-mode.message": "Maintenance Message",
|
||||||
"headers": "Headers",
|
"headers": "Headers",
|
||||||
"headers.allow-from": "Set ALLOW-FROM to Place NodeBB in an iFrame",
|
"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",
|
|
||||||
"headers.csp-frame-ancestors-help": "'none', 'self'(default) or list of URIs to allow.",
|
|
||||||
"headers.powered-by": "Customise the \"Powered By\" header sent by NodeBB",
|
"headers.powered-by": "Customise the \"Powered By\" header sent by NodeBB",
|
||||||
"headers.acao": "Access-Control-Allow-Origin",
|
"headers.acao": "Access-Control-Allow-Origin",
|
||||||
"headers.acao-regex": "Access-Control-Allow-Origin Regular Expression",
|
"headers.acao-regex": "Access-Control-Allow-Origin Regular Expression",
|
||||||
@@ -17,27 +15,14 @@
|
|||||||
"headers.acah": "Access-Control-Allow-Headers",
|
"headers.acah": "Access-Control-Allow-Headers",
|
||||||
"hsts": "Strict Transport Security",
|
"hsts": "Strict Transport Security",
|
||||||
"hsts.enabled": "Enabled HSTS (recommended)",
|
"hsts.enabled": "Enabled HSTS (recommended)",
|
||||||
"hsts.maxAge": "HSTS Max Age",
|
|
||||||
"hsts.subdomains": "Include subdomains in HSTS header",
|
"hsts.subdomains": "Include subdomains in HSTS header",
|
||||||
"hsts.preload": "Allow preloading of HSTS header",
|
"hsts.preload": "Allow preloading of HSTS header",
|
||||||
"hsts.help": "If enabled, an HSTS header will be set for this site. You can elect to include subdomains and preloading flags in your header. If in doubt, you can leave these unchecked. <a href=\"%1\">More information <i class=\"fa fa-external-link\"></i></a>",
|
"hsts.help": "If enabled, an HSTS header will be set for this site. You can elect to include subdomains and preloading flags in your header. If in doubt, you can leave these unchecked. <a href=\"%1\">More information <i class=\"fa fa-external-link\"></i></a>",
|
||||||
"traffic-management": "Traffic Management",
|
"traffic-management": "Traffic Management",
|
||||||
"traffic.help": "NodeBB uses a module that automatically denies requests in high-traffic situations. You can tune these settings here, although the defaults are a good starting point.",
|
"traffic.help": "NodeBB deploys equipped with a module that automatically denies requests in high-traffic situations. You can tune these settings here, although the defaults are a good starting point.",
|
||||||
"traffic.enable": "Enable Traffic Management",
|
"traffic.enable": "Enable Traffic Management",
|
||||||
"traffic.event-lag": "Event Loop Lag Threshold (in milliseconds)",
|
"traffic.event-lag": "Event Loop Lag Threshold (in milliseconds)",
|
||||||
"traffic.event-lag-help": "Lowering this value decreases wait times for page loads, but will also show the \"excessive load\" message to more users. (Restart required)",
|
"traffic.event-lag-help": "Lowering this value decreases wait times for page loads, but will also show the \"excessive load\" message to more users. (Restart required)",
|
||||||
"traffic.lag-check-interval": "Check Interval (in milliseconds)",
|
"traffic.lag-check-interval": "Check Interval (in milliseconds)",
|
||||||
"traffic.lag-check-interval-help": "Lowering this value causes NodeBB to become more sensitive to spikes in load, but may also cause the check to become too sensitive. (Restart required)",
|
"traffic.lag-check-interval-help": "Lowering this value causes NodeBB to become more sensitive to spikes in load, but may also cause the check to become too sensitive. (Restart required)"
|
||||||
|
|
||||||
"sockets.settings": "WebSocket Settings",
|
|
||||||
"sockets.max-attempts": "Max Reconnection Attempts",
|
|
||||||
"sockets.default-placeholder": "Default: %1",
|
|
||||||
"sockets.delay": "Reconnection Delay",
|
|
||||||
|
|
||||||
"analytics.settings": "Analytics Settings",
|
|
||||||
"analytics.max-cache": "Analytics Cache Max Value",
|
|
||||||
"analytics.max-cache-help": "On high-traffic installs, the cache could be exhausted continuously if there are more concurrent active users than the Max Cache value. (Restart required)",
|
|
||||||
"compression.settings": "Compression Settings",
|
|
||||||
"compression.enable": "Enable Compression",
|
|
||||||
"compression.help": "This setting enables gzip compression. For a high-traffic website in production, the best way to put compression in place is to implement it at a reverse proxy level. You can enable it here for testing purposes."
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"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.",
|
|
||||||
"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",
|
|
||||||
"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",
|
|
||||||
"no-description": "No description specified.",
|
|
||||||
"token-on-save": "Token will be generated once form is saved"
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
"max-length": "Maximum length of chat messages",
|
"max-length": "Maximum length of chat messages",
|
||||||
"max-room-size": "Maximum number of users in chat rooms",
|
"max-room-size": "Maximum number of users in chat rooms",
|
||||||
"delay": "Time between chat messages in milliseconds",
|
"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-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)"
|
"restrictions.seconds-delete-after": "Number of seconds a chat message will remain deletable. (0 disabled)"
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,5 @@
|
|||||||
"consent.blank-localised-default": "Leave blank to use NodeBB localised defaults",
|
"consent.blank-localised-default": "Leave blank to use NodeBB localised defaults",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"cookie-domain": "Session cookie domain",
|
"cookie-domain": "Session cookie domain",
|
||||||
"max-user-sessions": "Max active sessions per user",
|
|
||||||
"blank-default": "Leave blank for default"
|
"blank-default": "Leave blank for default"
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,12 @@
|
|||||||
"address-help": "The following email address refers to the email that the recipient will see in the \"From\" and \"Reply To\" fields.",
|
"address-help": "The following email address refers to the email that the recipient will see in the \"From\" and \"Reply To\" fields.",
|
||||||
"from": "From Name",
|
"from": "From Name",
|
||||||
"from-help": "The from name to display in the email.",
|
"from-help": "The from name to display in the email.",
|
||||||
|
"sendmail-rate-limit": "Send <em>X</em> emails...",
|
||||||
|
"sendmail-rate-delta": "... every <em>X</em> milliseconds",
|
||||||
|
"sendmail-rate-help": "Instructs the NodeBB mailer to limit the number of messages sent at once in order to not overwhelm email receiving services. These options do not apply if SMTP Transport is enabled (below).",
|
||||||
|
|
||||||
"smtp-transport": "SMTP Transport",
|
"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-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": "Select a service",
|
||||||
"smtp-transport.service-custom": "Custom Service",
|
"smtp-transport.service-custom": "Custom Service",
|
||||||
@@ -22,8 +25,6 @@
|
|||||||
"smtp-transport.username": "Username",
|
"smtp-transport.username": "Username",
|
||||||
"smtp-transport.username-help": "<b>For the Gmail service,</b> enter the full email address here, especially if you are using a Google Apps managed domain.",
|
"smtp-transport.username-help": "<b>For the Gmail service,</b> enter the full email address here, especially if you are using a Google Apps managed domain.",
|
||||||
"smtp-transport.password": "Password",
|
"smtp-transport.password": "Password",
|
||||||
"smtp-transport.pool": "Enable pooled connections",
|
|
||||||
"smtp-transport.pool-help": "Pooling connections prevents NodeBB from creating a new connection for every email. This option only applies if SMTP Transport is enabled.",
|
|
||||||
|
|
||||||
"template": "Edit Email Template",
|
"template": "Edit Email Template",
|
||||||
"template.select": "Select Email Template",
|
"template.select": "Select Email Template",
|
||||||
@@ -35,13 +36,5 @@
|
|||||||
"subscriptions": "Email Digests",
|
"subscriptions": "Email Digests",
|
||||||
"subscriptions.disable": "Disable email digests",
|
"subscriptions.disable": "Disable email digests",
|
||||||
"subscriptions.hour": "Digest Hour",
|
"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>",
|
"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 they have to enter an email address in order to proceed with registration. <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."
|
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,35 @@
|
|||||||
{
|
{
|
||||||
"site-settings": "اعدادات الموقع",
|
"site-settings": "Site Settings",
|
||||||
"title": "عنوان الموقع",
|
"title": "Site Title",
|
||||||
"title.short": "عنوان قصير",
|
"title.url": "URL",
|
||||||
"title.short-placeholder": "ان لم تقم بكتابة عنوان مختصر, سيتم استخدام عنوان الموقع الكلي",
|
|
||||||
"title.url": "Title Link URL",
|
|
||||||
"title.url-placeholder": "The URL of the site title",
|
"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. <br> 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.name": "Your Community Name",
|
||||||
"title.show-in-header": "Show Site Title in Header",
|
"title.show-in-header": "Show Site Title in Header",
|
||||||
"browser-title": "عنوان المتصفح",
|
"browser-title": "Browser Title",
|
||||||
"browser-title-help": "If no browser title is specified, the site title will be used",
|
"browser-title-help": "If no browser title is specified, the site title will be used",
|
||||||
"title-layout": "Title Layout",
|
"title-layout": "Title Layout",
|
||||||
"title-layout-help": "Define how the browser title will be structured ie. {pageTitle} | {browserTitle}",
|
"title-layout-help": "Define how the browser title will be structured ie. {pageTitle} | {browserTitle}",
|
||||||
"description.placeholder": "A short description about your community",
|
"description.placeholder": "A short description about your community",
|
||||||
"description": "وصف الموقع",
|
"description": "Site Description",
|
||||||
"keywords": "الكلمات الدليله للموقع",
|
"keywords": "Site Keywords",
|
||||||
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
||||||
"logo": "شعار الموقع",
|
"logo": "Site Logo",
|
||||||
"logo.image": "صورة",
|
"logo.image": "Image",
|
||||||
"logo.image-placeholder": "Path to a logo to display on forum header",
|
"logo.image-placeholder": "Path to a logo to display on forum header",
|
||||||
"logo.upload": "رفع",
|
"logo.upload": "Upload",
|
||||||
"logo.url": "Logo Link URL",
|
"logo.url": "URL",
|
||||||
"logo.url-placeholder": "The URL of the site logo",
|
"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": "نص بديل",
|
"logo.alt-text": "Alt Text",
|
||||||
"log.alt-text-placeholder": "Alternative text for accessibility",
|
"log.alt-text-placeholder": "Alternative text for accessibility",
|
||||||
"favicon": "صورة المفضله",
|
"favicon": "Favicon",
|
||||||
"favicon.upload": "رفع",
|
"favicon.upload": "Upload",
|
||||||
"pwa": "Progressive Web App",
|
"touch-icon": "Homescreen/Touch Icon",
|
||||||
"touch-icon": "Touch Icon",
|
"touch-icon.upload": "Upload",
|
||||||
"touch-icon.upload": "رفع",
|
"touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
||||||
"touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
|
||||||
"maskable-icon": "Maskable (Homescreen) Icon",
|
|
||||||
"maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon.",
|
|
||||||
"outgoing-links": "Outgoing Links",
|
"outgoing-links": "Outgoing Links",
|
||||||
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
||||||
"search": "Search",
|
"search-default-sort-by": "Search default sort by",
|
||||||
"search-default-in": "Search In",
|
"outgoing-links.whitelist": "Domains to whitelist for bypassing the warning page"
|
||||||
"search-default-in-quick": "Quick Search In",
|
|
||||||
"search-default-sort-by": "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"
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
"private-groups": "Private Groups",
|
"private-groups": "Private Groups",
|
||||||
"private-groups.help": "If enabled, joining of groups requires the approval of the group owner <em>(Default: enabled)</em>",
|
"private-groups.help": "If enabled, joining of groups requires the approval of the group owner <em>(Default: enabled)</em>",
|
||||||
"private-groups.warning": "<strong>Beware!</strong> If this option is disabled and you have private groups, they automatically become public.",
|
"private-groups.warning": "<strong>Beware!</strong> If this option is disabled and you have private groups, they automatically become public.",
|
||||||
"allow-multiple-badges": "Allow Multiple Badges",
|
|
||||||
"allow-multiple-badges-help": "This flag can be used to allow users to select multiple group badges, requires theme support.",
|
"allow-multiple-badges-help": "This flag can be used to allow users to select multiple group badges, requires theme support.",
|
||||||
"max-name-length": "Maximum Group Name Length",
|
"max-name-length": "Maximum Group Name Length",
|
||||||
"max-title-length": "Maximum Group Title Length",
|
"max-title-length": "Maximum Group Title Length",
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
{
|
{
|
||||||
"settings": "Settings",
|
"handles": "Guest Handles",
|
||||||
"handles.enabled": "Allow guest handles",
|
"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\"",
|
"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",
|
|
||||||
"reply-notifications.enabled": "Allow guests to generate reply notifications"
|
|
||||||
}
|
}
|
||||||
@@ -3,5 +3,5 @@
|
|||||||
"welcome-notification": "Welcome Notification",
|
"welcome-notification": "Welcome Notification",
|
||||||
"welcome-notification-link": "Welcome Notification Link",
|
"welcome-notification-link": "Welcome Notification Link",
|
||||||
"welcome-notification-uid": "Welcome Notification User (UID)",
|
"welcome-notification-uid": "Welcome Notification User (UID)",
|
||||||
"post-queue-notification-uid": "Post Queue User (UID)"
|
"notification-alert-timeout": "Notification Alert Timeout"
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
{
|
{
|
||||||
"pagination": "Pagination Settings",
|
"pagination": "Pagination Settings",
|
||||||
"enable": "Paginate topics and posts instead of using infinite scroll.",
|
"enable": "Paginate topics and posts instead of using infinite scroll.",
|
||||||
"posts": "Post Pagination",
|
|
||||||
"topics": "Topic Pagination",
|
"topics": "Topic Pagination",
|
||||||
"posts-per-page": "Posts per Page",
|
"posts-per-page": "Posts per Page",
|
||||||
"max-posts-per-page": "Maximum posts per page",
|
"max-posts-per-page": "Maximum posts per page",
|
||||||
"categories": "Category Pagination",
|
"categories": "Category Pagination",
|
||||||
"topics-per-page": "Topics per Page",
|
"topics-per-page": "Topics per Page",
|
||||||
"max-topics-per-page": "Maximum topics per page",
|
"max-topics-per-page": "Maximum topics per page"
|
||||||
"categories-per-page": "Categories per page"
|
|
||||||
}
|
}
|
||||||
@@ -34,18 +34,14 @@
|
|||||||
"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>",
|
"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>",
|
||||||
"timestamp.necro-threshold": "Necro Threshold (in days)",
|
"timestamp.necro-threshold": "Necro Threshold (in days)",
|
||||||
"timestamp.necro-threshold-help": "A message will be shown between posts if the time between them is longer than the necro threshold. (Default: <code>7</code>, or one week). Set to 0 to disable.</em>",
|
"timestamp.necro-threshold-help": "A message will be shown between posts if the time between them is longer than the necro threshold. (Default: <code>7</code>, or one week). Set to 0 to disable.</em>",
|
||||||
"timestamp.topic-views-interval": "Increment topic views interval (in minutes)",
|
|
||||||
"timestamp.topic-views-interval-help": "Topic views will only increment once every X minutes as defined by this setting.",
|
|
||||||
"teaser": "Teaser Post",
|
"teaser": "Teaser Post",
|
||||||
"teaser.last-post": "Last – Show the latest post, including the original post, if no replies",
|
"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.last-reply": "Last – Show the latest reply, or a \"No replies\" placeholder if no replies",
|
||||||
"teaser.first": "First",
|
"teaser.first": "First",
|
||||||
"showPostPreviewsOnHover": "Show a preview of posts when mouse overed",
|
|
||||||
"unread": "Unread Settings",
|
"unread": "Unread Settings",
|
||||||
"unread.cutoff": "Unread cutoff days",
|
"unread.cutoff": "Unread cutoff days",
|
||||||
"unread.min-track-last": "Minimum posts in topic before tracking last read",
|
"unread.min-track-last": "Minimum posts in topic before tracking last read",
|
||||||
"recent": "Recent Settings",
|
"recent": "Recent Settings",
|
||||||
"recent.max-topics": "Maximum topics on /recent",
|
|
||||||
"recent.categoryFilter.disable": "Disable filtering of topics in ignored categories on the /recent page",
|
"recent.categoryFilter.disable": "Disable filtering of topics in ignored categories on the /recent page",
|
||||||
"signature": "Signature Settings",
|
"signature": "Signature Settings",
|
||||||
"signature.disable": "Disable signatures",
|
"signature.disable": "Disable signatures",
|
||||||
@@ -57,9 +53,6 @@
|
|||||||
"composer.show-help": "Show \"Help\" tab",
|
"composer.show-help": "Show \"Help\" tab",
|
||||||
"composer.enable-plugin-help": "Allow plugins to add content to the help tab",
|
"composer.enable-plugin-help": "Allow plugins to add content to the help tab",
|
||||||
"composer.custom-help": "Custom Help Text",
|
"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": "IP Tracking",
|
||||||
"ip-tracking.each-post": "Track IP Address for each post",
|
"ip-tracking.each-post": "Track IP Address for each post",
|
||||||
"enable-post-history": "Enable Post History"
|
"enable-post-history": "Enable Post History"
|
||||||
|
|||||||
@@ -5,18 +5,10 @@
|
|||||||
"votes-are-public": "All Votes Are Public",
|
"votes-are-public": "All Votes Are Public",
|
||||||
"thresholds": "Activity Thresholds",
|
"thresholds": "Activity Thresholds",
|
||||||
"min-rep-downvote": "Minimum reputation to downvote posts",
|
"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-flag": "Minimum reputation to flag posts",
|
"min-rep-flag": "Minimum reputation to flag posts",
|
||||||
"min-rep-website": "Minimum reputation to add \"Website\" to user profile",
|
"min-rep-website": "Minimum reputation to add \"Website\" to user profile",
|
||||||
"min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile",
|
"min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile",
|
||||||
"min-rep-signature": "Minimum reputation to add \"Signature\" to user profile",
|
"min-rep-signature": "Minimum reputation to add \"Signature\" to user profile",
|
||||||
"min-rep-profile-picture": "Minimum reputation to add \"Profile Picture\" to user profile",
|
"min-rep-profile-picture": "Minimum reputation to add \"Profile Picture\" to user profile",
|
||||||
"min-rep-cover-picture": "Minimum reputation to add \"Cover Picture\" to user profile",
|
"min-rep-cover-picture": "Minimum reputation to add \"Cover Picture\" to user profile"
|
||||||
|
|
||||||
"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-resolve-on-ban": "Automatically resolve all of a user's tickets when they are banned"
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
{
|
{
|
||||||
"tag": "Tag Settings",
|
"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.",
|
|
||||||
"min-per-topic": "Minimum Tags per Topic",
|
"min-per-topic": "Minimum Tags per Topic",
|
||||||
"max-per-topic": "Maximum Tags per Topic",
|
"max-per-topic": "Maximum Tags per Topic",
|
||||||
"min-length": "Minimum Tag Length",
|
"min-length": "Minimum Tag Length",
|
||||||
"max-length": "Maximum Tag Length",
|
"max-length": "Maximum Tag Length",
|
||||||
|
"goto-manage": "Click here to visit the tag management page.",
|
||||||
"related-topics": "Related Topics",
|
"related-topics": "Related Topics",
|
||||||
"max-related-topics": "Maximum related topics to display (if supported by theme)"
|
"max-related-topics": "Maximum related topics to display (if supported by theme)"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"posts": "المشاركات",
|
"posts": "المشاركات",
|
||||||
|
"allow-files": "السماح للأعضاء بتحميل الملفات الإعتيادية",
|
||||||
"private": "جعل الملفات التي تم رفعها خاصة",
|
"private": "جعل الملفات التي تم رفعها خاصة",
|
||||||
"strip-exif-data": "Strip EXIF Data",
|
"strip-exif-data": "Strip EXIF Data",
|
||||||
"private-extensions": "File extensions to make private",
|
"private-extensions": "File extensions to make private",
|
||||||
@@ -20,9 +21,6 @@
|
|||||||
"topic-thumb-size": "حجم الصورة المصغرة للموضوع",
|
"topic-thumb-size": "حجم الصورة المصغرة للموضوع",
|
||||||
"allowed-file-extensions": "إمتدادات الملفات المسموح بها",
|
"allowed-file-extensions": "إمتدادات الملفات المسموح بها",
|
||||||
"allowed-file-extensions-help": "أدخل قائمة بامتدادات الملفات مفصولة بفواصل (مثال: <code>pdf,xls,doc</code>). القائمة الفارغة تعني أن كل الامتدادات مسموح بها.",
|
"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": "الصورة الرمزية للملف الشخصي",
|
"profile-avatars": "الصورة الرمزية للملف الشخصي",
|
||||||
"allow-profile-image-uploads": "السماح للأعضاء برفع الصور الرمزية",
|
"allow-profile-image-uploads": "السماح للأعضاء برفع الصور الرمزية",
|
||||||
"convert-profile-image-png": "تحويل إمتداد الصور الرمزية المرفوعه الى PNG",
|
"convert-profile-image-png": "تحويل إمتداد الصور الرمزية المرفوعه الى PNG",
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
{
|
{
|
||||||
"authentication": "المصادقة",
|
"authentication": "المصادقة",
|
||||||
|
"require-email-confirmation": "يطلب تأكيد البريد الإلكتروني",
|
||||||
"email-confirm-interval": "لا يمكن للمستخدم إعادة إرسال رسالة تأكيد البريد الالكتروني حتى مرور",
|
"email-confirm-interval": "لا يمكن للمستخدم إعادة إرسال رسالة تأكيد البريد الالكتروني حتى مرور",
|
||||||
"email-confirm-email2": "دقائق",
|
"email-confirm-email2": "دقائق",
|
||||||
"allow-login-with": "السماح بتسجيل الدخول باستخدام",
|
"allow-login-with": "السماح بتسجيل الدخول باستخدام",
|
||||||
"allow-login-with.username-email": "اسم المستخدم أو البريد الالكتروني",
|
"allow-login-with.username-email": "اسم المستخدم أو البريد الالكتروني",
|
||||||
"allow-login-with.username": "اسم المستخدم فقط",
|
"allow-login-with.username": "اسم المستخدم فقط",
|
||||||
|
"allow-login-with.email": "البريد الالكتروني فقط",
|
||||||
"account-settings": "إعدادت الحساب",
|
"account-settings": "إعدادت الحساب",
|
||||||
"gdpr_enabled": "Enable GDPR consent collection",
|
"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_help": "When enabled, all new registrants will be required to explicitly give consent for data collection and usage under the <a href=\"https://eugdpr.org/the-regulation/gdpr-faqs/\">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-username-changes": "عدم السماح بتغيير اسم المستخدم",
|
||||||
"disable-email-changes": "عدم السماح بتغيير البريد الالكتروني",
|
"disable-email-changes": "عدم السماح بتغيير البريد الالكتروني",
|
||||||
"disable-password-changes": "عدم السماح بتغيير كلمة المرور",
|
"disable-password-changes": "عدم السماح بتغيير كلمة المرور",
|
||||||
"allow-account-deletion": "السماح بحذف الحساب",
|
"allow-account-deletion": "السماح بحذف الحساب",
|
||||||
"hide-fullname": "إخفاء الإسم الكامل عن المستخدمين",
|
"hide-fullname": "إخفاء الإسم الكامل عن المستخدمين",
|
||||||
"hide-email": "إخفاء البريد الإلكتروني عن المستخدمين",
|
"hide-email": "إخفاء البريد الإلكتروني عن المستخدمين",
|
||||||
"show-fullname-as-displayname": "Show user's full name as their display name if available",
|
|
||||||
"themes": "القوالب",
|
"themes": "القوالب",
|
||||||
"disable-user-skins": "منع المستخدمين من اختيار سمة مخصص",
|
"disable-user-skins": "منع المستخدمين من اختيار سمة مخصص",
|
||||||
"account-protection": "حماية الحساب",
|
"account-protection": "حماية الحساب",
|
||||||
@@ -42,9 +43,6 @@
|
|||||||
"registration-type.disabled": "لا يوجد تسجيل",
|
"registration-type.disabled": "لا يوجد تسجيل",
|
||||||
"registration-type.help": "Normal - Users can register from the /register page.<br/>\nInvite Only - Users can invite others from the <a href=\"%1/users\" target=\"_blank\">users</a> page.<br/>\nAdmin Invite Only - Only administrators can invite others from <a href=\"%1/users\" target=\"_blank\">users</a> and <a href=\"%1/admin/manage/users\">admin/manage/users</a> pages.<br/>\nNo registration - No user registration.<br/>",
|
"registration-type.help": "Normal - Users can register from the /register page.<br/>\nInvite Only - Users can invite others from the <a href=\"%1/users\" target=\"_blank\">users</a> page.<br/>\nAdmin Invite Only - Only administrators can invite others from <a href=\"%1/users\" target=\"_blank\">users</a> and <a href=\"%1/admin/manage/users\">admin/manage/users</a> pages.<br/>\nNo registration - No user registration.<br/>",
|
||||||
"registration-approval-type.help": "Normal - Users are registered immediately.<br/>\nAdmin Approval - User registrations are placed in an <a href=\"%1/admin/manage/registration\">approval queue</a> for administrators.<br/>\nAdmin Approval for IPs - Normal for new users, Admin Approval for IP addresses that already have an account.<br/>",
|
"registration-approval-type.help": "Normal - Users are registered immediately.<br/>\nAdmin Approval - User registrations are placed in an <a href=\"%1/admin/manage/registration\">approval queue</a> for administrators.<br/>\nAdmin Approval for IPs - Normal for new users, Admin Approval for IP addresses that already have an account.<br/>",
|
||||||
"registration-queue-auto-approve-time": "Automatic Approval Time",
|
|
||||||
"registration-queue-auto-approve-time-help": "Hours before user is approved automatically. 0 to disable.",
|
|
||||||
"registration-queue-show-average-time": "Show users average time it takes to approve a new user",
|
|
||||||
"registration.max-invites": "الحد الأقصى للدعوات لكل عضو",
|
"registration.max-invites": "الحد الأقصى للدعوات لكل عضو",
|
||||||
"max-invites": "الحد الأقصى للدعوات لكل عضو",
|
"max-invites": "الحد الأقصى للدعوات لكل عضو",
|
||||||
"max-invites-help": "0 لعدم تحديد قيود، الإدارة تحصل على دعوات لامحدودة <br> هذا الخيار يعمل فقط عند تحديد خيار \"بالدعوات فقط\"",
|
"max-invites-help": "0 لعدم تحديد قيود، الإدارة تحصل على دعوات لامحدودة <br> هذا الخيار يعمل فقط عند تحديد خيار \"بالدعوات فقط\"",
|
||||||
@@ -64,12 +62,10 @@
|
|||||||
"restrict-chat": "السماح فقط برسائل الدردشة من المستخدمين الذين أتبعهم",
|
"restrict-chat": "السماح فقط برسائل الدردشة من المستخدمين الذين أتبعهم",
|
||||||
"outgoing-new-tab": "Open outgoing links in new tab",
|
"outgoing-new-tab": "Open outgoing links in new tab",
|
||||||
"topic-search": "Enable In-Topic Searching",
|
"topic-search": "Enable In-Topic Searching",
|
||||||
"update-url-with-post-index": "Update url with post index while browsing topics",
|
|
||||||
"digest-freq": "Subscribe to Digest",
|
"digest-freq": "Subscribe to Digest",
|
||||||
"digest-freq.off": "Off",
|
"digest-freq.off": "Off",
|
||||||
"digest-freq.daily": "Daily",
|
"digest-freq.daily": "Daily",
|
||||||
"digest-freq.weekly": "Weekly",
|
"digest-freq.weekly": "Weekly",
|
||||||
"digest-freq.biweekly": "Bi-Weekly",
|
|
||||||
"digest-freq.monthly": "Monthly",
|
"digest-freq.monthly": "Monthly",
|
||||||
"email-chat-notifs": "Send an email if a new chat message arrives and I am not online",
|
"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",
|
"email-post-notif": "Send an email when replies are made to topics I am subscribed to",
|
||||||
|
|||||||
@@ -18,6 +18,5 @@
|
|||||||
"watching.message": "You are now watching updates from this category and all subcategories",
|
"watching.message": "You are now watching updates from this category and all subcategories",
|
||||||
"notwatching.message": "You are not watching 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",
|
"ignoring.message": "You are now ignoring updates from this category and all subcategories",
|
||||||
"watched-categories": "الأقسام المُتابعة",
|
"watched-categories": "الأقسام المُتابعة"
|
||||||
"x-more-categories": "%1 more categories"
|
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,7 @@
|
|||||||
"greeting_no_name": "مرحبًا",
|
"greeting_no_name": "مرحبًا",
|
||||||
"greeting_with_name": "مرحبًا بك يا %1",
|
"greeting_with_name": "مرحبًا بك يا %1",
|
||||||
"email.verify-your-email.subject": "Please verify your email",
|
"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.text1": "Your email address has changed!",
|
||||||
"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).",
|
|
||||||
"welcome.text1": "شكرًا على تسجيلك في %1!",
|
"welcome.text1": "شكرًا على تسجيلك في %1!",
|
||||||
"welcome.text2": "لتفعيل حسابك، نحتاج إلى التأكد من صحة عنوان البريد الإلكتروني الذي سجلت به.",
|
"welcome.text2": "لتفعيل حسابك، نحتاج إلى التأكد من صحة عنوان البريد الإلكتروني الذي سجلت به.",
|
||||||
"welcome.text3": "تم قبول نتسجيلك ، يمكنك الدخول باتسخدام اسم المستخدم و كلمة المرور.",
|
"welcome.text3": "تم قبول نتسجيلك ، يمكنك الدخول باتسخدام اسم المستخدم و كلمة المرور.",
|
||||||
@@ -23,8 +21,6 @@
|
|||||||
"reset.notify.text1": "نحيطك علما أن كلمة مرورك قد تم تغييرها في %1",
|
"reset.notify.text1": "نحيطك علما أن كلمة مرورك قد تم تغييرها في %1",
|
||||||
"reset.notify.text2": "إن لم يكن لديك علم بهذا، المرجو إشعار مدبر النظام بأسرع مايمكن.",
|
"reset.notify.text2": "إن لم يكن لديك علم بهذا، المرجو إشعار مدبر النظام بأسرع مايمكن.",
|
||||||
"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",
|
"digest.cta": "انقر هنا لمشاهدة %1",
|
||||||
"digest.unsub.info": "تم إرسال هذا الإشعار بآخر المستجدات وفقا لخيارات تسجيلكم.",
|
"digest.unsub.info": "تم إرسال هذا الإشعار بآخر المستجدات وفقا لخيارات تسجيلكم.",
|
||||||
"digest.day": "يوم",
|
"digest.day": "يوم",
|
||||||
@@ -48,8 +44,6 @@
|
|||||||
"unsub.cta": "انقر هنا لتغيير تلك الإعدادات",
|
"unsub.cta": "انقر هنا لتغيير تلك الإعدادات",
|
||||||
"unsubscribe": "unsubscribe",
|
"unsubscribe": "unsubscribe",
|
||||||
"unsub.success": "You will no longer receive emails from the <strong>%1</strong> mailing list",
|
"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.subject": "You have been banned from %1",
|
||||||
"banned.text1": "The user %1 has been banned from %2.",
|
"banned.text1": "The user %1 has been banned from %2.",
|
||||||
"banned.text2": "This ban will last until %1.",
|
"banned.text2": "This ban will last until %1.",
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
{
|
{
|
||||||
"invalid-data": "بيانات غير صحيحة",
|
"invalid-data": "بيانات غير صحيحة",
|
||||||
"invalid-json": "Invalid JSON",
|
"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": "لم تقم بتسجيل الدخول",
|
"not-logged-in": "لم تقم بتسجيل الدخول",
|
||||||
"account-locked": "تم حظر حسابك مؤقتًا.",
|
"account-locked": "تم حظر حسابك مؤقتًا.",
|
||||||
"search-requires-login": "البحث في المنتدى يتطلب حساب - الرجاء تسجيل الدخول أو التسجيل",
|
"search-requires-login": "البحث في المنتدى يتطلب حساب - الرجاء تسجيل الدخول أو التسجيل",
|
||||||
@@ -11,8 +9,6 @@
|
|||||||
"invalid-tid": "موضوع غير متواجد",
|
"invalid-tid": "موضوع غير متواجد",
|
||||||
"invalid-pid": "رد غير موجود",
|
"invalid-pid": "رد غير موجود",
|
||||||
"invalid-uid": "مستخدم غير موجود",
|
"invalid-uid": "مستخدم غير موجود",
|
||||||
"invalid-mid": "Invalid Chat Message ID",
|
|
||||||
"invalid-date": "A valid date must be provided",
|
|
||||||
"invalid-username": "اسم المستخدم غير مقبول",
|
"invalid-username": "اسم المستخدم غير مقبول",
|
||||||
"invalid-email": "البريد الاكتروني غير مقبول",
|
"invalid-email": "البريد الاكتروني غير مقبول",
|
||||||
"invalid-fullname": "Invalid Fullname",
|
"invalid-fullname": "Invalid Fullname",
|
||||||
@@ -25,21 +21,15 @@
|
|||||||
"invalid-username-or-password": "المرجود تحديد اسم مستخدم و كلمة مرور",
|
"invalid-username-or-password": "المرجود تحديد اسم مستخدم و كلمة مرور",
|
||||||
"invalid-search-term": "كلمة البحث غير صحيحة",
|
"invalid-search-term": "كلمة البحث غير صحيحة",
|
||||||
"invalid-url": "Invalid URL",
|
"invalid-url": "Invalid URL",
|
||||||
"invalid-event": "Invalid event: %1",
|
|
||||||
"local-login-disabled": "Local login system has been disabled for non-privileged accounts.",
|
"local-login-disabled": "Local login system has been disabled for non-privileged accounts.",
|
||||||
"csrf-invalid": "لم تتمكن من تسجيل الدخول. هنالك أحتمال ان جلستك انتهت. رجاءًا حاول مرة اخرى.",
|
"csrf-invalid": "لم تتمكن من تسجيل الدخول. هنالك أحتمال ان جلستك انتهت. رجاءًا حاول مرة اخرى.",
|
||||||
"invalid-path": "Invalid path",
|
|
||||||
"folder-exists": "Folder exists",
|
|
||||||
"invalid-pagination-value": "رقم الصفحة غير صحيح ، يجب أن يكون بين %1 و %2 .",
|
"invalid-pagination-value": "رقم الصفحة غير صحيح ، يجب أن يكون بين %1 و %2 .",
|
||||||
"username-taken": "اسم المستخدم مأخوذ",
|
"username-taken": "اسم المستخدم مأخوذ",
|
||||||
"email-taken": "البريد الالكتروني مأخوذ",
|
"email-taken": "البريد الالكتروني مأخوذ",
|
||||||
"email-nochange": "The email entered is the same as the email already on file.",
|
"email-not-confirmed": "You are unable to post until your email is confirmed, please click here to confirm your email.",
|
||||||
"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-chat": "لا يمكنك الدردشة حتى تقوم بتأكيد بريدك الإلكتروني، الرجاء إضغط هنا لتأكيد بريدك اﻹلكتروني.",
|
"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.",
|
"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": "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.",
|
"no-email-to-confirm": "هذا المنتدى يستلزم تفعيل بريدك الإلكتروني، انقر هنا من فضلك لإدخاله.",
|
||||||
"user-doesnt-have-email": "User \"%1\" does not have an email set.",
|
|
||||||
"email-confirm-failed": "لم نستطع تفعيل بريدك الإلكتروني، المرجو المحاولة لاحقًا.",
|
"email-confirm-failed": "لم نستطع تفعيل بريدك الإلكتروني، المرجو المحاولة لاحقًا.",
|
||||||
"confirm-email-already-sent": "لقد تم ارسال بريد التأكيد، الرجاء اﻹنتظار 1% دقائق لإعادة اﻹرسال",
|
"confirm-email-already-sent": "لقد تم ارسال بريد التأكيد، الرجاء اﻹنتظار 1% دقائق لإعادة اﻹرسال",
|
||||||
"sendmail-not-found": "The sendmail executable could not be found, please ensure it is installed and executable by the user running NodeBB.",
|
"sendmail-not-found": "The sendmail executable could not be found, please ensure it is installed and executable by the user running NodeBB.",
|
||||||
@@ -48,7 +38,6 @@
|
|||||||
"username-too-long": "اسم المستخدم طويل",
|
"username-too-long": "اسم المستخدم طويل",
|
||||||
"password-too-long": "كلمة السر طويلة ",
|
"password-too-long": "كلمة السر طويلة ",
|
||||||
"reset-rate-limited": "Too many password reset requests (rate limited)",
|
"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": "المستخدم محظور",
|
||||||
"user-banned-reason": "Sorry, this account has been banned (Reason: %1)",
|
"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-banned-reason-until": "Sorry, this account has been banned until %1 (Reason: %2)",
|
||||||
@@ -91,27 +80,15 @@
|
|||||||
"tag-too-long": "Please enter a shorter tag. Tags can't be longer than %1 character(s)",
|
"tag-too-long": "Please enter a shorter tag. Tags can't be longer than %1 character(s)",
|
||||||
"not-enough-tags": "Not enough tags. Topics must have at least %1 tag(s)",
|
"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)",
|
"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": "الرجاء الانتظار حتى يكتمل الرفع.",
|
"still-uploading": "الرجاء الانتظار حتى يكتمل الرفع.",
|
||||||
"file-too-big": "الحد الأقصى لرفع الملفات %1 كيلو بت. رجاءًا ارفع ملف أصغر",
|
"file-too-big": "الحد الأقصى لرفع الملفات %1 كيلو بت. رجاءًا ارفع ملف أصغر",
|
||||||
"guest-upload-disabled": "خاصية رفع الملفات غير مفعلة للزوار.",
|
"guest-upload-disabled": "خاصية رفع الملفات غير مفعلة للزوار.",
|
||||||
"cors-error": "Unable to upload image due to misconfigured CORS",
|
"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.",
|
|
||||||
"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-bookmarked": "You have already bookmarked this post",
|
||||||
"already-unbookmarked": "You have already unbookmarked this post",
|
"already-unbookmarked": "You have already unbookmarked this post",
|
||||||
"cant-ban-other-admins": "لايمكن حظر مدبر نظام آخر.",
|
"cant-ban-other-admins": "لايمكن حظر مدبر نظام آخر.",
|
||||||
"cant-make-banned-users-admin": "You can't make banned users admin.",
|
|
||||||
"cant-remove-last-admin": "رجاءًا ، أضف مدير أخر قبل حذف صلاحيات الإدارة من حسابك.",
|
"cant-remove-last-admin": "رجاءًا ، أضف مدير أخر قبل حذف صلاحيات الإدارة من حسابك.",
|
||||||
"account-deletion-disabled": "Account deletion is disabled",
|
|
||||||
"cant-delete-admin": "رجاءًا أزل صلاحيات الإدارة قبل حذف الحساب. ",
|
"cant-delete-admin": "رجاءًا أزل صلاحيات الإدارة قبل حذف الحساب. ",
|
||||||
"already-deleting": "Already deleting",
|
|
||||||
"invalid-image": "Invalid image",
|
"invalid-image": "Invalid image",
|
||||||
"invalid-image-type": "نوع الصورة غير مدعوم. الأنواع المدعومة هي : %1",
|
"invalid-image-type": "نوع الصورة غير مدعوم. الأنواع المدعومة هي : %1",
|
||||||
"invalid-image-extension": "امتداد الصورة غير مدعوم.",
|
"invalid-image-extension": "امتداد الصورة غير مدعوم.",
|
||||||
@@ -145,12 +122,12 @@
|
|||||||
"invalid-chat-message": "الرسالة غير صالحة.",
|
"invalid-chat-message": "الرسالة غير صالحة.",
|
||||||
"chat-message-too-long": "Chat messages can not be longer than %1 characters.",
|
"chat-message-too-long": "Chat messages can not be longer than %1 characters.",
|
||||||
"cant-edit-chat-message": "غير مصرح لك بتعديل الرسالة.",
|
"cant-edit-chat-message": "غير مصرح لك بتعديل الرسالة.",
|
||||||
|
"cant-remove-last-user": "لأيمكنك إزالت اخر مستخدم.",
|
||||||
"cant-delete-chat-message": "غير مصرح لك بحذف الرسالة.",
|
"cant-delete-chat-message": "غير مصرح لك بحذف الرسالة.",
|
||||||
"chat-edit-duration-expired": "You are only allowed to edit chat messages for %1 second(s) after posting",
|
"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-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-deleted-already": "This chat message has already been deleted.",
|
||||||
"chat-restored-already": "This chat message has already been restored.",
|
"chat-restored-already": "This chat message has already been restored.",
|
||||||
"chat-room-does-not-exist": "Chat room does not exist.",
|
|
||||||
"already-voting-for-this-post": "لقد شاركت بالتصويت ، ألا تذكر؟",
|
"already-voting-for-this-post": "لقد شاركت بالتصويت ، ألا تذكر؟",
|
||||||
"reputation-system-disabled": "نظام السمعة معطل",
|
"reputation-system-disabled": "نظام السمعة معطل",
|
||||||
"downvoting-disabled": "التصويتات السلبية معطلة",
|
"downvoting-disabled": "التصويتات السلبية معطلة",
|
||||||
@@ -161,14 +138,8 @@
|
|||||||
"not-enough-reputation-min-rep-signature": "You do not have enough reputation to add a signature",
|
"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-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",
|
"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",
|
"already-flagged": "لقد بلغت عن هذه المشاركة من قبل.",
|
||||||
"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)",
|
|
||||||
"self-vote": "You cannot vote on your own post",
|
"self-vote": "You cannot vote on your own post",
|
||||||
"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\". سيواصل المنتدى خدمة العملاء السابقين لكن يجب عليك إلغاء أي تغيير قمت به قبل إعادة التحميل.",
|
"reload-failed": "المنتدى واجه مشكلة أثناء إعادة التحميل: \"%1\". سيواصل المنتدى خدمة العملاء السابقين لكن يجب عليك إلغاء أي تغيير قمت به قبل إعادة التحميل.",
|
||||||
"registration-error": "حدث خطأ أثناء التسجيل",
|
"registration-error": "حدث خطأ أثناء التسجيل",
|
||||||
"parse-error": "حدث خطأ ما أثناء تحليل استجابة الخادم",
|
"parse-error": "حدث خطأ ما أثناء تحليل استجابة الخادم",
|
||||||
@@ -182,32 +153,14 @@
|
|||||||
"cant-kick-self": "لا يمكنك طرد نفسك من المجموعة.",
|
"cant-kick-self": "لا يمكنك طرد نفسك من المجموعة.",
|
||||||
"no-users-selected": "لا يوجد مستخدم محدد.",
|
"no-users-selected": "لا يوجد مستخدم محدد.",
|
||||||
"invalid-home-page-route": "Invalid home page route",
|
"invalid-home-page-route": "Invalid home page route",
|
||||||
"invalid-session": "Invalid Session",
|
"invalid-session": "Session Mismatch",
|
||||||
"invalid-session-text": "It looks like your login session is no longer active. Please refresh this page.",
|
"invalid-session-text": "يبدو أن فترة التسجيل لم تعد قائمة او هي غير مطابقة مع الخادم. يرجى إعادة تحميل هذه الصفحة.",
|
||||||
"session-mismatch": "Session Mismatch",
|
|
||||||
"session-mismatch-text": "It looks like your login session no longer matches with the server. Please refresh this page.",
|
|
||||||
"no-topics-selected": "No topics selected!",
|
"no-topics-selected": "No topics selected!",
|
||||||
"cant-move-to-same-topic": "Can't move post to same topic!",
|
"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!",
|
|
||||||
"cannot-block-self": "You cannot block yourself!",
|
"cannot-block-self": "You cannot block yourself!",
|
||||||
"cannot-block-privileged": "You cannot block administrators or global moderators",
|
"cannot-block-privileged": "You cannot block administrators or global moderators",
|
||||||
"cannot-block-guest": "Guest are not able to block other users",
|
"cannot-block-guest": "Guest are not able to block other users",
|
||||||
"already-blocked": "This user is already blocked",
|
"already-blocked": "This user is already blocked",
|
||||||
"already-unblocked": "This user is already unblocked",
|
"already-unblocked": "This user is already unblocked",
|
||||||
"no-connection": "There seems to be a problem with your internet connection",
|
"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",
|
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
@@ -1,75 +1,58 @@
|
|||||||
{
|
{
|
||||||
"state": "الحالة",
|
"state": "State",
|
||||||
"reports": "Reports",
|
"reporter": "Reporter",
|
||||||
"first-reported": "First Reported",
|
"reported-at": "Reported At",
|
||||||
|
"description": "Description",
|
||||||
"no-flags": "Hooray! No flags found.",
|
"no-flags": "Hooray! No flags found.",
|
||||||
"assignee": "المحال إليه",
|
"assignee": "Assignee",
|
||||||
"update": "تحديث",
|
"update": "Update",
|
||||||
"updated": "تم التحديث",
|
"updated": "Updated",
|
||||||
"resolved": "Resolved",
|
|
||||||
"target-purged": "The content this flag referred to has been purged and is no longer available.",
|
"target-purged": "The content this flag referred to has been purged and is no longer available.",
|
||||||
|
|
||||||
"graph-label": "Daily Flags",
|
"graph-label": "Daily Flags",
|
||||||
"quick-filters": "Quick Filters",
|
"quick-filters": "Quick Filters",
|
||||||
"filter-active": "There are one or more filters active in this list of flags",
|
"filter-active": "There are one or more filters active in this list of flags",
|
||||||
"filter-reset": "ازالة الفلاتر",
|
"filter-reset": "Remove Filters",
|
||||||
"filters": "خيارات الفلتر",
|
"filters": "Filter Options",
|
||||||
"filter-reporterId": "Reporter UID",
|
"filter-reporterId": "Reporter UID",
|
||||||
"filter-targetUid": "Flagged UID",
|
"filter-targetUid": "Flagged UID",
|
||||||
"filter-type": "عنوان العلامة",
|
"filter-type": "Flag Type",
|
||||||
"filter-type-all": "كل المحتوي",
|
"filter-type-all": "All Content",
|
||||||
"filter-type-post": "مشاركة",
|
"filter-type-post": "Post",
|
||||||
"filter-type-user": "مستخدم",
|
"filter-type-user": "User",
|
||||||
"filter-state": "الحالة",
|
"filter-state": "State",
|
||||||
"filter-assignee": "Assignee UID",
|
"filter-assignee": "Assignee UID",
|
||||||
"filter-cid": "Category",
|
"filter-cid": "Category",
|
||||||
"filter-quick-mine": "Assigned to me",
|
"filter-quick-mine": "Assigned to me",
|
||||||
"filter-cid-all": "All categories",
|
"filter-cid-all": "All categories",
|
||||||
"apply-filters": "Apply Filters",
|
"apply-filters": "Apply Filters",
|
||||||
"more-filters": "More Filters",
|
|
||||||
"fewer-filters": "Fewer Filters",
|
|
||||||
|
|
||||||
"quick-actions": "اجراءات سريعه",
|
"quick-links": "Quick Links",
|
||||||
"flagged-user": "Flagged User",
|
"flagged-user": "Flagged User",
|
||||||
"view-profile": "مشاهدة الملف الشخصي",
|
"view-profile": "View Profile",
|
||||||
"start-new-chat": "بدء محادثه جديده",
|
"start-new-chat": "Start New Chat",
|
||||||
"go-to-target": "View Flag Target",
|
"go-to-target": "View Flag Target",
|
||||||
"assign-to-me": "Assign To Me",
|
|
||||||
"delete-post": "حذف المشاركة",
|
|
||||||
"purge-post": "Purge Post",
|
|
||||||
"restore-post": "استرجاع المشاركة",
|
|
||||||
|
|
||||||
"user-view": "مشاهدة الملف الشخصي",
|
"user-view": "View Profile",
|
||||||
"user-edit": "تعديل الملف الشخصي",
|
"user-edit": "Edit Profile",
|
||||||
|
|
||||||
"notes": "Flag Notes",
|
"notes": "Flag Notes",
|
||||||
"add-note": "اضافة ملاحظة",
|
"add-note": "Add Note",
|
||||||
"no-notes": "No shared notes.",
|
"no-notes": "No shared notes.",
|
||||||
"delete-note-confirm": "Are you sure you want to delete this flag note?",
|
|
||||||
"note-added": "Note Added",
|
|
||||||
"note-deleted": "Note Deleted",
|
|
||||||
|
|
||||||
"history": "Account & Flag History",
|
"history": "Flag History",
|
||||||
|
"back": "Back to Flags List",
|
||||||
"no-history": "No flag history.",
|
"no-history": "No flag history.",
|
||||||
|
|
||||||
"state-all": "All states",
|
"state-all": "All states",
|
||||||
"state-open": "New/Open",
|
"state-open": "New/Open",
|
||||||
"state-wip": "Work in Progress",
|
"state-wip": "Work in Progress",
|
||||||
"state-resolved": "تم حلها",
|
"state-resolved": "Resolved",
|
||||||
"state-rejected": "تم رفضها",
|
"state-rejected": "Rejected",
|
||||||
"no-assignee": "Not Assigned",
|
"no-assignee": "Not Assigned",
|
||||||
|
"note-added": "Note Added",
|
||||||
|
|
||||||
"sort": "Sort by",
|
"modal-title": "Report Inappropriate Content",
|
||||||
"sort-newest": "Newest first",
|
|
||||||
"sort-oldest": "Oldest first",
|
|
||||||
"sort-reports": "Most reports",
|
|
||||||
"sort-all": "All flag types...",
|
|
||||||
"sort-posts-only": "Posts only...",
|
|
||||||
"sort-downvotes": "Most downvotes",
|
|
||||||
"sort-upvotes": "Most upvotes",
|
|
||||||
"sort-replies": "Most replies",
|
|
||||||
|
|
||||||
"modal-title": "Report Content",
|
|
||||||
"modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.",
|
"modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.",
|
||||||
"modal-reason-spam": "Spam",
|
"modal-reason-spam": "Spam",
|
||||||
"modal-reason-offensive": "Offensive",
|
"modal-reason-offensive": "Offensive",
|
||||||
@@ -77,9 +60,7 @@
|
|||||||
"modal-reason-custom": "Reason for reporting this content...",
|
"modal-reason-custom": "Reason for reporting this content...",
|
||||||
"modal-submit": "Submit Report",
|
"modal-submit": "Submit Report",
|
||||||
"modal-submit-success": "Content has been flagged for moderation.",
|
"modal-submit-success": "Content has been flagged for moderation.",
|
||||||
|
"modal-submit-confirm": "Confirm Submission",
|
||||||
"bulk-actions": "Bulk Actions",
|
"modal-submit-confirm-text": "You have a custom reason specified already. Are you sure you wish to submit via quick-report?",
|
||||||
"bulk-resolve": "Resolve Flag(s)",
|
"modal-submit-confirm-text-help": "Submitting a quick report will overwrite any custom reasons defined."
|
||||||
"bulk-success": "%1 flags updated",
|
|
||||||
"flagged-timeago-readable": "Flagged <span class=\"timeago\" title=\"%1\"></span> (%2)"
|
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
"header.unread": "غير مقروء",
|
"header.unread": "غير مقروء",
|
||||||
"header.tags": "وسم",
|
"header.tags": "وسم",
|
||||||
"header.popular": "الأكثر شهرة",
|
"header.popular": "الأكثر شهرة",
|
||||||
"header.top": "Top",
|
|
||||||
"header.users": "المستخدمين",
|
"header.users": "المستخدمين",
|
||||||
"header.groups": "المجموعات",
|
"header.groups": "المجموعات",
|
||||||
"header.chats": "المحادثات",
|
"header.chats": "المحادثات",
|
||||||
@@ -46,31 +45,24 @@
|
|||||||
"alert.success": "نجاح",
|
"alert.success": "نجاح",
|
||||||
"alert.error": "خطأ",
|
"alert.error": "خطأ",
|
||||||
"alert.banned": "محظور",
|
"alert.banned": "محظور",
|
||||||
"alert.banned.message": "You have just been banned, your access is now restricted.",
|
"alert.banned.message": "لقد تم حظر حسابك. سيتم تسجيل الخروج.",
|
||||||
"alert.unbanned": "Unbanned",
|
|
||||||
"alert.unbanned.message": "Your ban has been lifted.",
|
|
||||||
"alert.unfollow": "أنت لا تتابع %1 بعد الآن!",
|
"alert.unfollow": "أنت لا تتابع %1 بعد الآن!",
|
||||||
"alert.follow": "أنت الآن تتابع %1!",
|
"alert.follow": "أنت الآن تتابع %1!",
|
||||||
"users": "الأعضاء",
|
"users": "الأعضاء",
|
||||||
"topics": "المواضيع",
|
"topics": "المواضيع",
|
||||||
"posts": "المشاركات",
|
"posts": "المشاركات",
|
||||||
"x-posts": "%1 posts",
|
|
||||||
"best": "الأفضل",
|
"best": "الأفضل",
|
||||||
"votes": "Votes",
|
"votes": "Votes",
|
||||||
"x-votes": "%1 votes",
|
|
||||||
"voters": "Voters",
|
|
||||||
"upvoters": "الموافقين",
|
"upvoters": "الموافقين",
|
||||||
"upvoted": "مصوت بالموجب",
|
"upvoted": "مصوت بالموجب",
|
||||||
"downvoters": "مصوتين بالسالب",
|
"downvoters": "مصوتين بالسالب",
|
||||||
"downvoted": "مصوت بالسالب",
|
"downvoted": "مصوت بالسالب",
|
||||||
"views": "المشاهدات",
|
"views": "المشاهدات",
|
||||||
"posters": "Posters",
|
|
||||||
"reputation": "السمعة",
|
"reputation": "السمعة",
|
||||||
"lastpost": "Last post",
|
"lastpost": "Last post",
|
||||||
"firstpost": "First post",
|
"firstpost": "First post",
|
||||||
"read_more": "اقرأ المزيد",
|
"read_more": "اقرأ المزيد",
|
||||||
"more": "المزيد",
|
"more": "المزيد",
|
||||||
"none": "None",
|
|
||||||
"posted_ago_by_guest": "كتب %1 بواسطة زائر",
|
"posted_ago_by_guest": "كتب %1 بواسطة زائر",
|
||||||
"posted_ago_by": "كتب %1 بواسطة %2",
|
"posted_ago_by": "كتب %1 بواسطة %2",
|
||||||
"posted_ago": "كتب %1",
|
"posted_ago": "كتب %1",
|
||||||
@@ -96,8 +88,6 @@
|
|||||||
"guest": "زائر",
|
"guest": "زائر",
|
||||||
"guests": "الزوار",
|
"guests": "الزوار",
|
||||||
"former_user": "A Former User",
|
"former_user": "A Former User",
|
||||||
"system-user": "System",
|
|
||||||
"unknown-user": "Unknown user",
|
|
||||||
"updated.title": "تم تحديث المنتدى",
|
"updated.title": "تم تحديث المنتدى",
|
||||||
"updated.message": "لقد تم تحديث المنتدى إلى آخر نسخة للتو. إضغط هنا لإعادة تحميل الصفحة.",
|
"updated.message": "لقد تم تحديث المنتدى إلى آخر نسخة للتو. إضغط هنا لإعادة تحميل الصفحة.",
|
||||||
"privacy": "الخصوصية",
|
"privacy": "الخصوصية",
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
"details.member_count": "عدد اﻷعضاء",
|
"details.member_count": "عدد اﻷعضاء",
|
||||||
"details.creation_date": "تاريخ الإنشاء",
|
"details.creation_date": "تاريخ الإنشاء",
|
||||||
"details.description": "الوصف",
|
"details.description": "الوصف",
|
||||||
"details.member-post-cids": "Category IDs to display posts from",
|
|
||||||
"details.badge_preview": "معاينة الوسام",
|
"details.badge_preview": "معاينة الوسام",
|
||||||
"details.change_icon": "تغيير الأيقونة",
|
"details.change_icon": "تغيير الأيقونة",
|
||||||
"details.change_label_colour": "Change Label Colour",
|
"details.change_label_colour": "Change Label Colour",
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"username-email": "اسم المستخدم / البريد الإلكتروني",
|
"username-email": "اسم المستخدم / البريد الإلكتروني",
|
||||||
"username": "اسم المستخدم",
|
"username": "اسم المستخدم",
|
||||||
|
"email": "البريد الإلكتروني",
|
||||||
"remember_me": "تذكرني؟",
|
"remember_me": "تذكرني؟",
|
||||||
"forgot_password": "نسيت كلمة المرور؟",
|
"forgot_password": "نسيت كلمة المرور؟",
|
||||||
"alternative_logins": "تسجيلات الدخول البديلة",
|
"alternative_logins": "تسجيلات الدخول البديلة",
|
||||||
"failed_login_attempt": "تسجيل الدخول غير ناجح",
|
"failed_login_attempt": "تسجيل الدخول غير ناجح",
|
||||||
"login_successful": "قمت بتسجيل الدخول بنجاح!",
|
"login_successful": "قمت بتسجيل الدخول بنجاح!",
|
||||||
"dont_have_account": "لا تملك حساب؟",
|
"dont_have_account": "لا تملك حساب؟",
|
||||||
"logged-out-due-to-inactivity": "لقد تم تسجيل خروجك من لوحة تحكم بسبب عدم نشاطك",
|
"logged-out-due-to-inactivity": "لقد تم تسجيل خروجك من لوحة تحكم بسبب عدم نشاطك"
|
||||||
"caps-lock-enabled": "Caps Lock is enabled"
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"chat.chatting_with": "Chat with",
|
"chat.chatting_with": "Chat with",
|
||||||
"chat.placeholder": "أكتب رسالة دردشة هنا، اضغط ENTER للإرسال",
|
"chat.placeholder": "أكتب رسالة دردشة هنا، اضغط ENTER للإرسال",
|
||||||
"chat.scroll-up-alert": "You are looking at older messages, click here to go to most recent message.",
|
|
||||||
"chat.send": "أرسل",
|
"chat.send": "أرسل",
|
||||||
"chat.no_active": "لا يوجد لديك دردشات نشطة.",
|
"chat.no_active": "لا يوجد لديك دردشات نشطة.",
|
||||||
"chat.user_typing": "%1 يكتب رسالة...",
|
"chat.user_typing": "%1 يكتب رسالة...",
|
||||||
@@ -13,7 +12,6 @@
|
|||||||
"chat.recent-chats": "آخر الدردشات",
|
"chat.recent-chats": "آخر الدردشات",
|
||||||
"chat.contacts": "الأصدقاء",
|
"chat.contacts": "الأصدقاء",
|
||||||
"chat.message-history": "تاريخ الرسائل",
|
"chat.message-history": "تاريخ الرسائل",
|
||||||
"chat.message-deleted": "Message Deleted",
|
|
||||||
"chat.options": "Chat options",
|
"chat.options": "Chat options",
|
||||||
"chat.pop-out": "افتح الدردشة في نافذة خاصة",
|
"chat.pop-out": "افتح الدردشة في نافذة خاصة",
|
||||||
"chat.minimize": "Minimize",
|
"chat.minimize": "Minimize",
|
||||||
@@ -54,29 +52,15 @@
|
|||||||
"composer.formatting.strikethrough": "Strikethrough",
|
"composer.formatting.strikethrough": "Strikethrough",
|
||||||
"composer.formatting.code": "Code",
|
"composer.formatting.code": "Code",
|
||||||
"composer.formatting.link": "Link",
|
"composer.formatting.link": "Link",
|
||||||
"composer.formatting.picture": "Image Link",
|
"composer.formatting.picture": "Picture",
|
||||||
"composer.upload-picture": "Upload Image",
|
"composer.upload-picture": "Upload Image",
|
||||||
"composer.upload-file": "Upload File",
|
"composer.upload-file": "Upload File",
|
||||||
"composer.zen_mode": "Zen Mode",
|
"composer.zen_mode": "Zen Mode",
|
||||||
"composer.select_category": "Select a category",
|
"composer.select_category": "Select a category",
|
||||||
"composer.textarea.placeholder": "Enter your post content here, drag and drop images",
|
|
||||||
"composer.schedule-for": "Schedule topic for",
|
|
||||||
"composer.schedule-date": "Date",
|
|
||||||
"composer.schedule-time": "Time",
|
|
||||||
"composer.cancel-scheduling": "Cancel Scheduling",
|
|
||||||
"composer.set-schedule-date": "Set Date",
|
|
||||||
"bootbox.ok": "OK",
|
"bootbox.ok": "OK",
|
||||||
"bootbox.cancel": "إلغاء",
|
"bootbox.cancel": "إلغاء",
|
||||||
"bootbox.confirm": "تأكيد",
|
"bootbox.confirm": "تأكيد",
|
||||||
"bootbox.submit": "Submit",
|
|
||||||
"bootbox.send": "Send",
|
|
||||||
"cover.dragging_title": "Cover Photo Positioning",
|
"cover.dragging_title": "Cover Photo Positioning",
|
||||||
"cover.dragging_message": "Drag the cover photo to the desired position and click \"Save\"",
|
"cover.dragging_message": "Drag the cover photo to the desired position and click \"Save\"",
|
||||||
"cover.saved": "Cover photo image and position saved",
|
"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?"
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
"topics": "مواضيع",
|
"topics": "مواضيع",
|
||||||
"replies": "ردود",
|
"replies": "ردود",
|
||||||
"chat": "محادثات",
|
"chat": "محادثات",
|
||||||
"group-chat": "Group Chats",
|
|
||||||
"follows": "متابعون",
|
"follows": "متابعون",
|
||||||
"upvote": "الموافقين",
|
"upvote": "الموافقين",
|
||||||
"new-flags": "New Flags",
|
"new-flags": "New Flags",
|
||||||
@@ -36,7 +35,6 @@
|
|||||||
"user_posted_to_dual": "<strong>%1</strong> and <strong>%2</strong> have posted replies to: <strong>%3</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_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_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": "<strong>%1</strong> صار يتابعك.",
|
||||||
"user_started_following_you_dual": "<strong>%1</strong> and <strong>%2</strong> started following you.",
|
"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.",
|
"user_started_following_you_multiple": "<strong>%1</strong> and %2 others started following you.",
|
||||||
@@ -44,13 +42,6 @@
|
|||||||
"new_register_multiple": "There are <strong>%1</strong> registration requests awaiting review.",
|
"new_register_multiple": "There are <strong>%1</strong> registration requests awaiting review.",
|
||||||
"flag_assigned_to_you": "تم تخصيص العلامة 1% لك",
|
"flag_assigned_to_you": "تم تخصيص العلامة 1% لك",
|
||||||
"post_awaiting_review": "Post awaiting review",
|
"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": "تم التحقق من عنوان البريد الإلكتروني",
|
||||||
"email-confirmed-message": "شكرًا على إثبات صحة عنوان بريدك الإلكتروني. صار حسابك مفعلًا بالكامل.",
|
"email-confirmed-message": "شكرًا على إثبات صحة عنوان بريدك الإلكتروني. صار حسابك مفعلًا بالكامل.",
|
||||||
"email-confirm-error-message": "حدث خطأ أثناء التحقق من عنوان بريدك الإلكتروني. ربما رمز التفعيل خاطئ أو انتهت صلاحيته.",
|
"email-confirm-error-message": "حدث خطأ أثناء التحقق من عنوان بريدك الإلكتروني. ربما رمز التفعيل خاطئ أو انتهت صلاحيته.",
|
||||||
@@ -62,12 +53,9 @@
|
|||||||
"notificationType_upvote": "عندما يوافقك احدهم على منشورك",
|
"notificationType_upvote": "عندما يوافقك احدهم على منشورك",
|
||||||
"notificationType_new-topic": "When someone you follow posts a topic",
|
"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_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_follow": "When someone starts following you",
|
||||||
"notificationType_new-chat": "When you receive a chat message",
|
"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-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_group-request-membership": "When someone requests to join a group you own",
|
||||||
"notificationType_new-register": "When someone gets added to registration queue",
|
"notificationType_new-register": "When someone gets added to registration queue",
|
||||||
"notificationType_post-queue": "When a new post is queued",
|
"notificationType_post-queue": "When a new post is queued",
|
||||||
|
|||||||