add docs from readme on the site
This commit is contained in:
@@ -3,3 +3,227 @@ title: API
|
||||
parent: Contributing
|
||||
order: 400
|
||||
---
|
||||
|
||||
## Authorization
|
||||
|
||||
- `GET /auth/{provider}/login?from=http://url&site=site_id&session=1` - perform "social" login with one of [supported providers](#register-oauth2-providers) and redirect to `url`. Presence of `session` (any non-zero value) change the default cookie expiration and makes them session-only
|
||||
- `GET /auth/logout` - logout
|
||||
|
||||
```go
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
Picture string `json:"picture"`
|
||||
Admin bool `json:"admin"`
|
||||
Blocked bool `json:"block"`
|
||||
Verified bool `json:"verified"`
|
||||
}
|
||||
```
|
||||
|
||||
## Commenting
|
||||
|
||||
- `POST /api/v1/comment` - add a comment, _auth required_
|
||||
|
||||
```go
|
||||
type Comment struct {
|
||||
ID string `json:"id"` // comment ID, read only
|
||||
ParentID string `json:"pid"` // parent ID
|
||||
Text string `json:"text"` // comment text, after md processing
|
||||
Orig string `json:"orig"` // original comment text
|
||||
User User `json:"user"` // user info, read only
|
||||
Locator Locator `json:"locator"` // post locator
|
||||
Score int `json:"score"` // comment score, read only
|
||||
Vote int `json:"vote"` // vote for the current user, -1/1/0
|
||||
Controversy float64 `json:"controversy,omitempty"` // comment controversy, read only
|
||||
Timestamp time.Time `json:"time"` // time stamp, read only
|
||||
Edit *Edit `json:"edit,omitempty" bson:"edit,omitempty"` // pointer to have empty default in JSON response
|
||||
Pin bool `json:"pin"` // pinned status, read only
|
||||
Delete bool `json:"delete"` // delete status, read only
|
||||
PostTitle string `json:"title"` // post title
|
||||
}
|
||||
|
||||
type Locator struct {
|
||||
SiteID string `json:"site"` // site ID
|
||||
URL string `json:"url"` // post URL
|
||||
}
|
||||
|
||||
type Edit struct {
|
||||
Timestamp time.Time `json:"time" bson:"time"`
|
||||
Summary string `json:"summary"`
|
||||
}
|
||||
```
|
||||
|
||||
- `POST /api/v1/preview` - preview comment in HTML. Body is `Comment` to render
|
||||
- `GET /api/v1/find?site=site-id&url=post-url&sort=fld&format=tree|plain` - find all comments for given post
|
||||
|
||||
This is the primary call used by UI to show comments for the given post. It can return comments in two formats - `plain` and `tree`. In plain format result will be sorted list of `Comment`. In tree format this is going to be tree-like object with this structure:
|
||||
|
||||
```go
|
||||
type Tree struct {
|
||||
Nodes []Node `json:"comments"`
|
||||
Info store.PostInfo `json:"info,omitempty"`
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Comment store.Comment `json:"comment"`
|
||||
Replies []Node `json:"replies,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
Sort can be `time`, `active` or `score`. Supported sort order with prefix -/+, i.e. `-time`. For `tree` mode sort will be applied to top-level comments only and all replies are always sorted by time.
|
||||
|
||||
- `PUT /api/v1/comment/{id}?site=site-id&url=post-url` - edit comment, allowed once in `EDIT_TIME` minutes since creation. Body is `EditRequest` JSON
|
||||
|
||||
```go
|
||||
type EditRequest struct {
|
||||
Text string `json:"text"` // updated text
|
||||
Summary string `json:"summary"` // optional, summary of the edit
|
||||
Delete bool `json:"delete"` // delete flag
|
||||
}{}
|
||||
```
|
||||
|
||||
- `GET /api/v1/last/{max}?site=site-id&since=ts-msec` - get up to `{max}` last comments, `since` (epoch time, milliseconds) is optional
|
||||
- `GET /api/v1/id/{id}?site=site-id` - get comment by `comment id`
|
||||
- `GET /api/v1/comments?site=site-id&user=id&limit=N` - get comment by `user id`, returns `response` object
|
||||
|
||||
```go
|
||||
type response struct {
|
||||
Comments []store.Comment `json:"comments"`
|
||||
Count int `json:"count"`
|
||||
}{}
|
||||
```
|
||||
|
||||
- `GET /api/v1/count?site=site-id&url=post-url` - get comment's count for `{url}`
|
||||
- `POST /api/v1/count?site=siteID` - get number of comments for posts from post body (list of post IDs)
|
||||
- `GET /api/v1/list?site=site-id&limit=5&skip=2` - list commented posts, returns array or `PostInfo`, limit=0 will return all posts
|
||||
|
||||
```go
|
||||
type PostInfo struct {
|
||||
URL string `json:"url"`
|
||||
Count int `json:"count"`
|
||||
ReadOnly bool `json:"read_only,omitempty"`
|
||||
FirstTS time.Time `json:"first_time,omitempty"`
|
||||
LastTS time.Time `json:"last_time,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
- `GET /api/v1/user` - get user info, _auth required_
|
||||
- `PUT /api/v1/vote/{id}?site=site-id&url=post-url&vote=1` - vote for comment. `vote`=1 will increase score, -1 decrease, _auth required_
|
||||
- `GET /api/v1/userdata?site=site-id` - export all user data to gz stream, _auth required_
|
||||
- `POST /api/v1/deleteme?site=site-id` - request deletion of user data, _auth required_
|
||||
- `GET /api/v1/config?site=site-id` - returns configuration (parameters) for given site
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
Version string `json:"version"`
|
||||
EditDuration int `json:"edit_duration"`
|
||||
MaxCommentSize int `json:"max_comment_size"`
|
||||
Admins []string `json:"admins"`
|
||||
AdminEmail string `json:"admin_email"`
|
||||
Auth []string `json:"auth_providers"`
|
||||
LowScore int `json:"low_score"`
|
||||
CriticalScore int `json:"critical_score"`
|
||||
PositiveScore bool `json:"positive_score"`
|
||||
ReadOnlyAge int `json:"readonly_age"`
|
||||
MaxImageSize int `json:"max_image_size"`
|
||||
EmojiEnabled bool `json:"emoji_enabled"`
|
||||
}
|
||||
```
|
||||
|
||||
- `GET /api/v1/info?site=site-idd&url=post-url` - returns `PostInfo` for site and URL
|
||||
|
||||
## Streaming API
|
||||
|
||||
Streaming API provides server-sent events for post updates as well as a site update:
|
||||
|
||||
- `GET /api/v1/stream/info?site=site-idd&url=post-url&since=unix_ts_msec` - returns stream (`event: info`) with `PostInfo` records for the site and URL. `since` is optional
|
||||
- `GET /api/v1/stream/last?site=site-id&since=unix_ts_msec` - returns updates stream (`event: last`) with comments for the site, `since` is optional
|
||||
|
||||
<details><summary>Response example</summary>
|
||||
|
||||
```
|
||||
data: {"url":"https://radio-t.com/blah1","count":2,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.142872-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":3,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.157709-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":4,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.172991-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":5,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.188429-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":6,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.204742-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":7,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.220692-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":8,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.23817-05:00"}
|
||||
|
||||
event: info
|
||||
data: {"url":"https://radio-t.com/blah1","count":9,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.254669-05:00"}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## RSS Feeds
|
||||
|
||||
- `GET /api/v1/rss/post?site=site-id&url=post-url` - RSS feed for a post
|
||||
- `GET /api/v1/rss/site?site=site-id` - RSS feed for given site
|
||||
- `GET /api/v1/rss/reply?site=site-id&user=user-id` - RSS feed for replies to user's comments
|
||||
|
||||
## Images Management
|
||||
|
||||
- `GET /api/v1/picture/{user}/{id}` - load stored image
|
||||
- `POST /api/v1/picture` - upload and store image, uses post form with `FormFile("file")`. Returns `{"id": user/imgid}`, _auth required_
|
||||
|
||||
_returned ID should be appended to load image URL on caller side_
|
||||
|
||||
## Email Subscription
|
||||
|
||||
- `GET /api/v1/email?site=site-id` - get user's email, _auth required_
|
||||
- `POST /api/v1/email/subscribe?site=site-id&address=user@example.org` - makes confirmation token and sends it to user over email, _auth required_
|
||||
|
||||
Trying to subscribe to the same email a second time will return response code `409 Conflict` and explaining error message
|
||||
|
||||
- `POST /api/v1/email/confirm?site=site-id&tkn=token` - uses provided token parameter to set email for the user, _auth required_
|
||||
|
||||
Setting email subscribe user for all first-level replies to his messages
|
||||
|
||||
- `DELETE /api/v1/email?site=siteID` - removes user's email, _auth required_
|
||||
|
||||
## Admin
|
||||
|
||||
- `DELETE /api/v1/admin/comment/{id}?site=site-id&url=post-url` - delete comment by `id`
|
||||
- `PUT /api/v1/admin/user/{userid}?site=site-id&block=1&ttl=7d` - block or unblock user with optional TTL (default=permanent)
|
||||
- `GET api/v1/admin/blocked&site=site-id` - list of blocked user IDs
|
||||
|
||||
```go
|
||||
type BlockedUser struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Until time.Time `json:"time"`
|
||||
}
|
||||
```
|
||||
|
||||
- `GET /api/v1/admin/export?site=site-id&mode=[stream|file]` - export all comments to JSON stream or gz file
|
||||
- `POST /api/v1/admin/import?site=site-id` - import comments from the backup, uses post body
|
||||
- `POST /api/v1/admin/import/form?site=site-id` - import comments from the backup, user post form
|
||||
- `POST /api/v1/admin/remap?site=site-id` - remap comments to different URLs. Expect list of "from-url new-url" pairs separated by \n. From-url and new-url parts are separated by space. If URLs end with an asterisk (\*) it means matching by the prefix. Remap procedure based on export/import chain so make the backup first
|
||||
|
||||
```
|
||||
http://oldsite.com* https://newsite.com*
|
||||
http://oldsite.com/from-old-page/1 https://newsite.com/to-new-page/1
|
||||
```
|
||||
|
||||
- `GET /api/v1/admin/wait?site=site-id` - wait for completion for any async migration ops (import or remap)
|
||||
- `PUT /api/v1/admin/pin/{id}?site=site-id&url=post-url&pin=1` - pin or unpin comment
|
||||
- `GET /api/v1/admin/user/{userid}?site=site-id` - get user's info
|
||||
- `DELETE /api/v1/admin/user/{userid}?site=site-id` - delete all user's comments
|
||||
- `PUT /api/v1/admin/readonly?site=site-id&url=post-url&ro=1` - set read-only status
|
||||
- `PUT /api/v1/admin/verify/{userid}?site=site-id&verified=1` - set verified status
|
||||
- `GET /api/v1/admin/deleteme?token=token` - process deleteme user's request
|
||||
|
||||
_all admin calls require auth and admin privilege_
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
title: Code of Conduct
|
||||
parent: Contributing
|
||||
order: 100
|
||||
---
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
title: Development Environment
|
||||
menuTitle: Environment
|
||||
parent: Contributing
|
||||
order: 300
|
||||
---
|
||||
+3
-1
@@ -2,6 +2,8 @@
|
||||
title: Backend Development Guidelines
|
||||
menuTitle: Backend
|
||||
key: Backend Guidelines
|
||||
parent: Guidelines
|
||||
parent: Development
|
||||
order: 100
|
||||
---
|
||||
|
||||
In Progress...
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Frontend Development Guidelines
|
||||
menuTitle: Frontend
|
||||
key: Frontend Guidelines
|
||||
parent: Development
|
||||
order: 100
|
||||
---
|
||||
|
||||
### Code Style
|
||||
|
||||
- project uses TypeScript to statically analyze code
|
||||
- project uses `eslint` and `stylelint` to check frontend code. You can manually run via `npm run lint`
|
||||
- Git Hooks (via husky) installed automatically on `npm install` and check and try to fix code style if possible, otherwise commit will be rejected
|
||||
- if you want IDE integration, you need `eslint` and `stylelint` plugin to be installed
|
||||
|
||||
### CSS Styles
|
||||
|
||||
- now we are migrating to CSS Modules and this is a recommended way to stylization. A file with styles should be named like `component.module.css`
|
||||
- old component styles use BEM notation (at least it should): `block__element_modifier`. Also, there are `mix` classes: `block_modifier`
|
||||
- new way to naming CSS selectors is camel-case like `blockElemenModifier` and use `classnames` to combine it
|
||||
- component base style resides in the component's root directory with a name of component converted to kebab-case. For example, `ListComments` style is located in `./app/components/list-comments/list-component.tsx`
|
||||
- any other files should be named also in kebab-case. For example, `./app/utils/get-param.ts`
|
||||
|
||||
### Imports
|
||||
|
||||
- imports for TypeScript, JavaScript files should be without extension: `./index`, not `./index.ts`
|
||||
- if the file resides in the same directory or subdirectory import should be relative: `./types/something`
|
||||
- otherwise it should be imported by absolute path relative to `src` folder like `common/store` which mapped to `./app/common/store.ts` in webpack, tsconfig and Jest
|
||||
|
||||
### Testing
|
||||
|
||||
- project uses `jest` as test harness
|
||||
- Jest checks files that match regex `\.(test|spec)\.ts(x?)$`, i.e. `comment.test.tsx`, `comment.spec.ts`
|
||||
- tests are running on push attempt
|
||||
- example tests can be found in `./app/store/user/reducers.test.ts`, `./app/components/auth-panel/auth-panel.test.tsx`
|
||||
|
||||
### How to add new locale
|
||||
|
||||
Please see [this documentation](/site/src/docs/contributing/translations/index.md).
|
||||
|
||||
### Notes
|
||||
|
||||
- frontend part being bundled on docker env gets placed on `/src/web` and is available via `http://{host}/web`. For example, `embed.js` entry point will be available at `http://{host}/web/embed.js`
|
||||
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Development
|
||||
parent: Contributing
|
||||
order: 200
|
||||
---
|
||||
|
||||
You can use a fully functional local version to develop and test both frontend and backend. It requires at least 2GB RAM or swap enabled.
|
||||
|
||||
To bring it up run:
|
||||
|
||||
```shell
|
||||
# if you mainly work on backend
|
||||
cp compose-dev-backend.yml compose-private.yml
|
||||
# if you mainly work on frontend
|
||||
cp compose-dev-frontend.yml compose-private.yml
|
||||
# now, edit / debug `compose-private.yml` to your heart's content
|
||||
|
||||
# build and run
|
||||
docker-compose -f compose-private.yml build
|
||||
docker-compose -f compose-private.yml up
|
||||
```
|
||||
|
||||
It starts Remark42 on `127.0.0.1:8080` and adds local OAuth2 provider "Dev". To access the UI demo page go to `127.0.0.1:8080/web`. By default, you would be logged in as `dev_user` which is defined as admin. You can tweak any of [supported parameters](#parameters) in corresponded yml file.
|
||||
|
||||
Backend Docker Compose config by default skips running frontend related tests. Frontend Docker Compose config by default skips running backend related tests and sets `NODE_ENV=development` for frontend build.
|
||||
|
||||
### Backend development
|
||||
|
||||
To run backend locally (development mode, without Docker) you have to have the latest stable `go` toolchain [installed](https://golang.org/doc/install).
|
||||
|
||||
To run backend - `cd backend; go run app/main.go server --dbg --secret=12345 --url=http://127.0.0.1:8080 --admin-passwd=password --site=remark`. It stars backend service with embedded bolt store on port `8080` with basic auth, allowing to authenticate and run requests directly, like this:
|
||||
|
||||
`HTTP http://admin:password@127.0.0.1:8080/api/v1/find?site=remark&sort=-active&format=tree&url=http://127.0.0.1:8080`
|
||||
|
||||
### Frontend development
|
||||
|
||||
#### Developer guide
|
||||
|
||||
Frontend guide can be found here: [./frontend/README.md](./frontend/README.md).
|
||||
|
||||
#### Build
|
||||
|
||||
You should have at least 2GB RAM or swap enabled for building.
|
||||
|
||||
- install [Node.js 12.11](https://nodejs.org/en/) or higher
|
||||
- install [NPM 6.13.4](https://www.npmjs.com/package/npm)
|
||||
- run `npm install` inside `./frontend`
|
||||
- run `npm run build` there
|
||||
- result files will be saved in `./frontend/public`
|
||||
|
||||
**Note:** Running `npm install` will set up pre-commit hooks into your git repository. It used to reformat your frontend code using `prettier` and lint with `eslint` and `stylelint` before every commit.
|
||||
|
||||
#### Development server
|
||||
|
||||
For local development mode with Hot Reloading use `npm start` instead of `npm run build`. In this case, `webpack` will serve files using `webpack-dev-server` on `localhost:9000`. By visiting `127.0.0.1:9000/web` you will get a page with the main comments widget communicating with a demo server backend running on `https://demo.remark42.com`. But you will not be able to log in with any OAuth providers due to security reasons.
|
||||
|
||||
You can attach to the locally running backend by providing `REMARK_URL` environment variable.
|
||||
|
||||
```shell
|
||||
npx cross-env REMARK_URL=http://127.0.0.1:8080 npm start
|
||||
```
|
||||
|
||||
**Note:** If you want to redefine env variables such as `PORT` on your local instance you can add `.env` file to `./frontend` folder and rewrite variables as you wish. For such functional, we use `dotenv`.
|
||||
|
||||
The best way to start a local developer environment:
|
||||
|
||||
```shell
|
||||
cp compose-dev-frontend.yml compose-private-frontend.yml
|
||||
docker-compose -f compose-private-frontend.yml up --build
|
||||
cd frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Developer build running by `webpack-dev-server` supports devtools for [React](https://github.com/facebook/react-devtools) and
|
||||
[Redux](https://github.com/zalmoxisus/redux-devtools-extension).
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: Frontend Development Guidelines
|
||||
menuTitle: Frontend
|
||||
key: Frontend Guidelines
|
||||
parent: Guidelines
|
||||
order: 100
|
||||
---
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
title: Guidelines
|
||||
parent: Contributing
|
||||
order: 200
|
||||
---
|
||||
@@ -5,7 +5,7 @@ parent: Contributing
|
||||
order: 300
|
||||
---
|
||||
|
||||
## How to add new language translation to Remark42
|
||||
## Add a New Language to Remark42
|
||||
|
||||
Translation files are stored in [/frontend/app/locales](https://github.com/umputun/remark42/tree/master/frontend/app/locales)
|
||||
directory with `.json` extension and content like following:
|
||||
@@ -15,47 +15,38 @@ directory with `.json` extension and content like following:
|
||||
"anonymousLoginForm.length-limit": "Username must be at least 3 characters long",
|
||||
"anonymousLoginForm.log-in": "Log in",
|
||||
"anonymousLoginForm.symbol-limit": "Username must start from the letter and contain only latin letters, numbers, underscores, and spaces",
|
||||
<...>
|
||||
<...>
|
||||
}
|
||||
```
|
||||
|
||||
### How to add a new translation
|
||||
### Add a new translation
|
||||
|
||||
We truly appreciate people spending time contributing their translations to remark42. Please go through the steps
|
||||
below in order to have your translation start being available to all remark42 users and included in the next release.
|
||||
|
||||
1. create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please
|
||||
pull the latest changes from the upstream master branch. It could be done like that:
|
||||
```shell
|
||||
git remote add upstream https://github.com/umputun/remark42.git
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
git push
|
||||
```
|
||||
1. add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
||||
of the language you want to make the translation into to list in
|
||||
[frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
|
||||
1. run `npm install` in `frontend` folder
|
||||
1. run `npm run translation:extract` in `frontend` folder
|
||||
1. run `npm run translation:generate` in `frontend` folder
|
||||
1. translate all values in the newly created json file in
|
||||
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
|
||||
1. commit all changes above in your fork
|
||||
1. test your changes in the interface:
|
||||
1. Create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please pull the latest changes from the upstream master branch. It could be done like that:
|
||||
|
||||
1. uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133)
|
||||
and replace `ru` with your translation language code
|
||||
1. [run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands
|
||||
from the root directory of your remark42 fork:
|
||||
```shell
|
||||
git remote add upstream https://github.com/umputun/remark42.git
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
git push
|
||||
```
|
||||
|
||||
```shell
|
||||
docker-compose -f compose-dev-frontend.yml build
|
||||
docker-compose -f compose-dev-frontend.yml up
|
||||
```
|
||||
1. Add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) of the language you want to make the translation into to list in [frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
|
||||
1. Run `npm install` in `frontend` folder
|
||||
1. Run `npm run translation:extract` in `frontend` folder
|
||||
1. Run `npm run translation:generate` in `frontend` folder
|
||||
1. Translate all values in the newly created json file in
|
||||
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
|
||||
1. Commit all changes above in your fork
|
||||
1. Test your changes in the interface:
|
||||
|
||||
1. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment,
|
||||
and make sure your translation looks as you expect it to look
|
||||
1. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
|
||||
1. Uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133) and replace `ru` with your translation language code
|
||||
2. [Run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands from the root directory of your remark42 fork:
|
||||
`shell docker-compose -f compose-dev-frontend.yml build docker-compose -f compose-dev-frontend.yml up `
|
||||
|
||||
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42
|
||||
repo with your changes, attaching a screenshot or two from your local test instance to it
|
||||
3. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment, and make sure your translation looks as you expect it to look
|
||||
4. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
|
||||
|
||||
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42 repo with your changes, attaching a screenshot or two from your local test instance to it
|
||||
|
||||
Reference in New Issue
Block a user