mirror of
https://github.com/flameshikari/outline-ru.git
synced 2026-06-13 04:05:10 +03:00
@@ -0,0 +1,11 @@
|
||||
APP_PATH=/opt/outline
|
||||
SRC_PATH=./outline
|
||||
|
||||
ADDRESS=localhost
|
||||
PORT_OUTLINE=10240
|
||||
PORT_OIDC=10241
|
||||
PORT_REDIS=10242
|
||||
PORT_POSTGRES=10243
|
||||
|
||||
COMMON=outline
|
||||
SECRET=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
||||
@@ -9,8 +9,8 @@ on:
|
||||
- .github/workflows/**
|
||||
- outline/**
|
||||
- tools/translation.json
|
||||
- tools/language.patch
|
||||
- Dockerfile
|
||||
- tools/patches/**
|
||||
- Dockerfile.prod
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
@@ -79,6 +79,10 @@ jobs:
|
||||
cache-from: type=gha,scope=build-${{ matrix.arch }}
|
||||
cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }}
|
||||
platforms: linux/${{ matrix.arch }}
|
||||
file: Dockerfile.prod
|
||||
build-args: |
|
||||
APP_PATH=/opt/outline
|
||||
SRC_PATH=./outline
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
outputs: type=image,"name=${{ github.repository }},ghcr.io/${{ github.repository }}",push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
|
||||
+16
-37
@@ -1,18 +1,14 @@
|
||||
ARG APP_PATH=/opt/outline
|
||||
ARG SRC_PATH=./outline
|
||||
|
||||
FROM node:20 AS deps
|
||||
FROM node:20 AS base
|
||||
ARG APP_PATH
|
||||
ARG SRC_PATH
|
||||
WORKDIR $APP_PATH
|
||||
|
||||
FROM base AS deps
|
||||
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||
RUN yarn install --production=true --frozen-lockfile --network-timeout 1000000 && \
|
||||
yarn cache clean
|
||||
|
||||
FROM node:20 AS build
|
||||
ARG APP_PATH
|
||||
ARG SRC_PATH
|
||||
WORKDIR $APP_PATH
|
||||
FROM base AS build
|
||||
RUN apt-get update && \
|
||||
apt-get install -y patch cmake && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
@@ -22,35 +18,18 @@ ENV NODE_OPTIONS="--max-old-space-size=24000"
|
||||
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
|
||||
yarn cache clean
|
||||
COPY ${SRC_PATH} .
|
||||
COPY ./tools/language.patch .
|
||||
RUN patch -p1 < language.patch
|
||||
COPY ./tools/translation.json ./shared/i18n/locales/ru_RU/translation.json
|
||||
COPY --from=deps $APP_PATH/node_modules ./node_modules
|
||||
COPY ./tools/patches/* .
|
||||
RUN for patch in $(ls *.patch); do patch -p1 < $patch; done
|
||||
RUN cat <<EOF > /entrypoint.sh
|
||||
npx yarn concurrently -n "dev,i18n" \
|
||||
"yarn dev:watch" \
|
||||
"yarn nodemon \
|
||||
--watch './shared/i18n/locales/ru_RU' \
|
||||
--exec 'yarn build:i18n'"
|
||||
EOF
|
||||
ARG CDN_URL
|
||||
RUN yarn build && rm -rf node_modules
|
||||
|
||||
FROM node:22-slim AS release
|
||||
ARG APP_PATH
|
||||
ARG SRC_PATH
|
||||
WORKDIR $APP_PATH
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
ARG DATA_PATH=/var/lib/outline/data
|
||||
ARG USER=nodejs
|
||||
RUN useradd -m -U ${USER} && \
|
||||
mkdir -p ${DATA_PATH} && \
|
||||
chown -R ${USER}:${USER} ${APP_PATH} ${DATA_PATH}/.. && \
|
||||
chmod 1777 ${DATA_PATH}
|
||||
COPY --chown=${USER} --from=deps $APP_PATH/node_modules ./node_modules
|
||||
COPY --chown=${USER} --from=build $APP_PATH/build ./build
|
||||
COPY --chown=${USER} --from=build $APP_PATH/server ./server
|
||||
COPY --chown=${USER} --from=build $APP_PATH/public ./public
|
||||
COPY --chown=${USER} --from=build $APP_PATH/.sequelizerc .
|
||||
COPY --chown=${USER} --from=build $APP_PATH/package.json .
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
USER ${USER}
|
||||
EXPOSE ${PORT}
|
||||
VOLUME ${DATA_PATH}
|
||||
HEALTHCHECK --interval=1m CMD curl -fs localhost:${PORT}/_health | grep -q OK || exit 1
|
||||
CMD ["yarn", "start"]
|
||||
STOPSIGNAL SIGKILL
|
||||
ENTRYPOINT ["bash", "/entrypoint.sh"]
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
FROM node:20 AS base
|
||||
ARG APP_PATH
|
||||
ARG SRC_PATH
|
||||
WORKDIR $APP_PATH
|
||||
|
||||
FROM base AS deps
|
||||
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||
RUN yarn install --production=true --frozen-lockfile --network-timeout 1000000 && \
|
||||
yarn cache clean
|
||||
|
||||
FROM base AS build
|
||||
RUN apt-get update && \
|
||||
apt-get install -y patch cmake && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
COPY ${SRC_PATH}/patches ./patches
|
||||
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||
ENV NODE_OPTIONS="--max-old-space-size=24000"
|
||||
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
|
||||
yarn cache clean
|
||||
COPY ${SRC_PATH} .
|
||||
COPY ./tools/patches/lang.patch .
|
||||
RUN for patch in $(ls *.patch); do patch -p1 < $patch; done
|
||||
COPY ./tools/translation.json ./shared/i18n/locales/ru_RU/translation.json
|
||||
ARG CDN_URL
|
||||
RUN yarn build && rm -rf node_modules
|
||||
|
||||
FROM node:22-slim AS release
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
ARG DATA_PATH=/var/lib/outline/data
|
||||
ARG USER=nodejs
|
||||
ARG APP_PATH
|
||||
WORKDIR $APP_PATH
|
||||
RUN useradd -m -U ${USER} && \
|
||||
mkdir -p ${DATA_PATH} && \
|
||||
chown -R ${USER}:${USER} ${APP_PATH} ${DATA_PATH}/.. && \
|
||||
chmod 1777 ${DATA_PATH}
|
||||
COPY --chown=${USER} --from=deps $APP_PATH/node_modules ./node_modules
|
||||
COPY --chown=${USER} --from=build $APP_PATH/build ./build
|
||||
COPY --chown=${USER} --from=build $APP_PATH/server ./server
|
||||
COPY --chown=${USER} --from=build $APP_PATH/public ./public
|
||||
COPY --chown=${USER} --from=build $APP_PATH/.sequelizerc .
|
||||
COPY --chown=${USER} --from=build $APP_PATH/package.json .
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
USER ${USER}
|
||||
EXPOSE ${PORT}
|
||||
VOLUME ${DATA_PATH}
|
||||
HEALTHCHECK --interval=1m CMD curl -fs localhost:${PORT}/_health | grep -q OK || exit 1
|
||||
CMD ["yarn", "start"]
|
||||
@@ -35,23 +35,48 @@ services:
|
||||
|
||||
## 🛠️ Разработка
|
||||
|
||||
### Ключевые файлы
|
||||
|
||||
- русский перевод — [tools/translation.json](./tools/translation.json)
|
||||
- английский перевод — [outline/shared/i18n/locales/en_US/translation.json](https://github.com/outline/outline/blob/main/shared/i18n/locales/en_US/translation.json)
|
||||
- временный файл — [tools/translation.tmp.json]() (существует только локально)
|
||||
|
||||
### Быстрый старт
|
||||
|
||||
0. Клонирование репозитория с подмодулем:
|
||||
```sh
|
||||
git clone --recurse-submodules git@github.com:flameshikari/outline-ru.git
|
||||
```
|
||||
|
||||
1. Пулл изменений в подмодуле и переключение на коммит с целевой версией:
|
||||
```sh
|
||||
cd outline
|
||||
git pull --rebase --tags
|
||||
git checkout v0.85.0
|
||||
cd -
|
||||
```
|
||||
|
||||
2. Запуск контейнеров:
|
||||
```sh
|
||||
docker compose up -d --build
|
||||
```
|
||||
Веб-интерфейс Outline будет доступен по [этой ссылке](http://localhost:10240).
|
||||
|
||||
3. Формирование временного файла с помощью [tools/diff.py](./tools/diff.py):
|
||||
```sh
|
||||
python tools/diff.py
|
||||
```
|
||||
После можно приступить к переводу сфомированного временного файла. Любые изменения в русском переводе обновят [открытую веб-страницу](http://localhost:10240) через пару секунд.
|
||||
|
||||
### Описание
|
||||
|
||||
Контейнер Outline описан в одном [Dockerfile](./Dockerfile) на основе двух оригинальных с применением [патча](./tools/language.patch) поверх исходного кода Outline (он подключен к этому репозиторию в качестве подмодуля) и копированием [файла перевода](./tools/translation.json). Патч, помимо добавления отсутствующих строк в код, меняет некоторые upstream-ссылки, чтобы Outline мониторил этот контейнер на наличие новых версий, а не оригинальный.
|
||||
|
||||
В [docker-compose.yml](./docker-compose.yml) описаны четыре контейнера (кликабельные названия далее — это localhost-ссылки): [Outline](http://localhost:10240), Redis, Postgres и [тестовый OIDC-сервер](http://localhost:10241) (логин/пароль: `outline`). Также там описана вся конфигурация контейнеров; настраивайте под себя по желанию. После первой сборки контейнера большинство слоёв берётся из кэша, сам Outline после изменений пересобирается около полминуты-минуты (тут зависит от железа). Пайплайн примерно такой: перевёл → собрал → проверил.
|
||||
|
||||
Скрипт [diff.py](./tools/diff.py) используется для объединения переводов [английского](https://github.com/outline/outline/blob/main/shared/i18n/locales/en_US/translation.json) с [русским](./tools/translation.json) во временный файл `./tools/translation.tmp.json`. Скрипт не имеет интерактивного режима и каких-либо аргументов/опций, он просто запускается (с выводом некоторой полезной информации) и делает следующее:
|
||||
Скрипт [tools/diff.py](./tools/diff.py) используется для объединения английского и русского переводов во временный файл. Скрипт не имеет интерактивного режима и каких-либо аргументов/опций, он просто запускается (с выводом некоторой полезной информации) и делает следующее:
|
||||
|
||||
- сохраняет актуальные переведённые строки
|
||||
- удаляет неактуальные переведённые строки
|
||||
- если в файле перевода есть одинаковые key/value пары, то они считаются исключениями (например, `HTML` или `API`) и переносятся как есть
|
||||
- если в русском переводе есть одинаковые key/value пары, то они считаются исключениями (например, `HTML` или `API`) и переносятся как есть
|
||||
- новые непереведённые строки добавляются в конец
|
||||
|
||||
> Возможно, для коллективного перевода стоило использовать [Crowdin](https://crowdin.com), но что-то руки не дошли ¯\\_(ツ)_/¯
|
||||
|
||||
Во временном файле вручную делается перевод новых строк, а затем [файл перевода](./tools/translation.json) вручную заменяется временным файлом.
|
||||
|
||||
> Если во временном файле присутствуют две одинаковые непереведённые строки, но одна из них с суффиксом `_plural` (множественное число), например:
|
||||
>
|
||||
> ```json
|
||||
@@ -69,33 +94,3 @@ services:
|
||||
> "{{ count }} comment_2": "{{ count }} комментариев"
|
||||
> }
|
||||
> ```
|
||||
|
||||
### Команды
|
||||
|
||||
0. Клонирование репозитория с подмодулем
|
||||
```sh
|
||||
git clone --recurse-submodules git@github.com:flameshikari/outline-ru.git
|
||||
```
|
||||
|
||||
1. Пулл изменений в подмодуле и переключение на коммит с целевой версией
|
||||
```sh
|
||||
cd outline
|
||||
git pull --rebase --tags
|
||||
git checkout v0.85.0
|
||||
cd -
|
||||
```
|
||||
|
||||
2. Формирование временного файла с помощью [diff.py](./tools/diff.py)
|
||||
```sh
|
||||
python ./tools/diff.py
|
||||
```
|
||||
|
||||
3. Замена [файла перевода](./tools/translation.json) после перевода строк во временном файле
|
||||
```
|
||||
cp ./tools/translation.tmp.json ./tools/translation.json
|
||||
```
|
||||
|
||||
4. Сборка контейнера
|
||||
```sh
|
||||
docker compose up -d --build
|
||||
```
|
||||
@@ -0,0 +1,140 @@
|
||||
volumes:
|
||||
outline:
|
||||
name: outline
|
||||
outline-postgres:
|
||||
name: outline-postgres
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: outline
|
||||
|
||||
services:
|
||||
outline:
|
||||
container_name: outline
|
||||
image: flameshikari/outline-ru:nightly
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.prod
|
||||
args:
|
||||
- APP_PATH=${APP_PATH}
|
||||
- SRC_PATH=${SRC_PATH}
|
||||
network_mode: host
|
||||
pull_policy: always
|
||||
volumes:
|
||||
- outline:/var/lib/outline/data
|
||||
depends_on:
|
||||
- outline-postgres
|
||||
- outline-redis
|
||||
- outline-oidc
|
||||
environment:
|
||||
FILE_STORAGE: local
|
||||
FORCE_HTTPS: false
|
||||
PORT: ${PORT_OUTLINE}
|
||||
URL: http://${ADDRESS}:${PORT_OUTLINE}
|
||||
SECRET_KEY: ${SECRET}
|
||||
UTILS_SECRET: ${SECRET}
|
||||
REDIS_URL: redis://${ADDRESS}:${PORT_REDIS}
|
||||
DATABASE_URL: postgres://${COMMON}:${COMMON}@${ADDRESS}:${PORT_POSTGRES}/${COMMON}
|
||||
PGSSLMODE: disable
|
||||
OIDC_ISSUER_URL: http://${ADDRESS}:${PORT_OIDC}
|
||||
OIDC_CLIENT_ID: ${COMMON}
|
||||
OIDC_CLIENT_SECRET: ${COMMON}
|
||||
|
||||
outline-oidc:
|
||||
container_name: outline-oidc
|
||||
image: ghcr.io/soluto/oidc-server-mock:0.11.0
|
||||
ports:
|
||||
- ${PORT_OIDC}:80
|
||||
healthcheck:
|
||||
test: curl -fs ${ADDRESS}/health || exit 1
|
||||
start_period: 2s
|
||||
interval: 1s
|
||||
timeout: 100ms
|
||||
retries: 10
|
||||
environment:
|
||||
ASPNETCORE_URLS: http://+:80
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
CLIENTS_CONFIGURATION_INLINE: |
|
||||
[
|
||||
{
|
||||
"ClientId": "${COMMON}",
|
||||
"ClientSecrets": ["${COMMON}"],
|
||||
"RedirectUris": ["http://${ADDRESS}:${PORT_OUTLINE}/auth/oidc.callback"],
|
||||
"AllowedGrantTypes": ["authorization_code"],
|
||||
"AllowedScopes": ["openid", "profile", "email"],
|
||||
"RequirePkce": false
|
||||
}
|
||||
]
|
||||
USERS_CONFIGURATION_INLINE: |
|
||||
[
|
||||
{
|
||||
"SubjectId": "1",
|
||||
"Username": "${COMMON}",
|
||||
"Password": "${COMMON}",
|
||||
"Claims": [
|
||||
{
|
||||
"Type": "email",
|
||||
"Value": "mail@example.com",
|
||||
"ValueType": "string"
|
||||
},
|
||||
{
|
||||
"Type": "name",
|
||||
"Value": "Outline",
|
||||
"ValueType": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
SERVER_OPTIONS_INLINE: |
|
||||
{
|
||||
"AccessTokenJwtType": "JWT",
|
||||
"Discovery": {
|
||||
"ShowKeySet": true
|
||||
},
|
||||
"Authentication": {
|
||||
"CookieSameSiteMode": "Lax",
|
||||
"CheckSessionCookieSameSiteMode": "Lax"
|
||||
}
|
||||
}
|
||||
LOGIN_OPTIONS_INLINE: |
|
||||
{
|
||||
"AllowRememberLogin": false
|
||||
}
|
||||
LOGOUT_OPTIONS_INLINE: |
|
||||
{
|
||||
"AutomaticRedirectAfterSignOut": true
|
||||
}
|
||||
ASPNET_SERVICES_OPTIONS_INLINE: |
|
||||
{
|
||||
"ForwardedHeadersOptions": {
|
||||
"ForwardedHeaders" : "All"
|
||||
}
|
||||
}
|
||||
|
||||
outline-redis:
|
||||
container_name: outline-redis
|
||||
image: redis:7
|
||||
ports:
|
||||
- ${PORT_REDIS}:6379
|
||||
healthcheck:
|
||||
test: redis-cli ping
|
||||
interval: 10s
|
||||
timeout: 30s
|
||||
retries: 3
|
||||
|
||||
outline-postgres:
|
||||
container_name: outline-postgres
|
||||
image: postgres:17
|
||||
ports:
|
||||
- ${PORT_POSTGRES}:5432
|
||||
volumes:
|
||||
- outline-postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: pg_isready
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
environment:
|
||||
POSTGRES_USER: ${COMMON}
|
||||
POSTGRES_PASSWORD: ${COMMON}
|
||||
POSTGRES_DB: ${COMMON}
|
||||
+18
-118
@@ -10,131 +10,31 @@ networks:
|
||||
|
||||
services:
|
||||
outline:
|
||||
container_name: outline
|
||||
image: flameshikari/outline-ru:nightly
|
||||
build: .
|
||||
network_mode: host
|
||||
pull_policy: always
|
||||
volumes:
|
||||
- outline:/var/lib/outline/data
|
||||
extends:
|
||||
file: docker-compose.prod.yml
|
||||
service: outline
|
||||
image: !reset
|
||||
pull_policy: !reset
|
||||
build:
|
||||
dockerfile: !reset
|
||||
depends_on:
|
||||
- outline-postgres
|
||||
- outline-redis
|
||||
- outline-oidc
|
||||
environment:
|
||||
FILE_STORAGE: local
|
||||
FORCE_HTTPS: false
|
||||
PORT: 10240
|
||||
URL: http://localhost:10240
|
||||
SECRET_KEY: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
||||
UTILS_SECRET: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
||||
REDIS_URL: redis://localhost:10242
|
||||
DATABASE_URL: postgres://outline:outline@localhost:10243/outline
|
||||
PGSSLMODE: disable
|
||||
OIDC_ISSUER_URL: http://localhost:10241
|
||||
OIDC_CLIENT_ID: outline
|
||||
OIDC_CLIENT_SECRET: outline
|
||||
# OIDC_AUTH_URI: http://localhost:10241/connect/authorize
|
||||
# OIDC_TOKEN_URI: http://localhost:10241/connect/token
|
||||
# OIDC_USERINFO_URI: http://localhost:10241/connect/userinfo
|
||||
# OIDC_SCOPES: openid profile email
|
||||
# OIDC_USERNAME_CLAIM: username
|
||||
volumes:
|
||||
- ./tools/translation.json:/opt/outline/shared/i18n/locales/ru_RU/translation.json
|
||||
|
||||
outline-oidc:
|
||||
container_name: outline-oidc
|
||||
image: ghcr.io/soluto/oidc-server-mock:0.11.0
|
||||
ports:
|
||||
- 10241:80
|
||||
healthcheck:
|
||||
test: curl -fs localhost/health || exit 1
|
||||
start_period: 2s
|
||||
interval: 1s
|
||||
timeout: 100ms
|
||||
retries: 10
|
||||
environment:
|
||||
ASPNETCORE_URLS: http://+:80
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
CLIENTS_CONFIGURATION_INLINE: |
|
||||
[
|
||||
{
|
||||
"ClientId": "outline",
|
||||
"ClientSecrets": ["outline"],
|
||||
"RedirectUris": ["http://localhost:10240/auth/oidc.callback"],
|
||||
"AllowedGrantTypes": ["authorization_code"],
|
||||
"AllowedScopes": ["openid", "profile", "email"],
|
||||
"RequirePkce": false
|
||||
}
|
||||
]
|
||||
USERS_CONFIGURATION_INLINE: |
|
||||
[
|
||||
{
|
||||
"SubjectId": "1",
|
||||
"Username": "outline",
|
||||
"Password": "outline",
|
||||
"Claims": [
|
||||
{
|
||||
"Type": "email",
|
||||
"Value": "mail@example.com",
|
||||
"ValueType": "string"
|
||||
},
|
||||
{
|
||||
"Type": "name",
|
||||
"Value": "Outline",
|
||||
"ValueType": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
SERVER_OPTIONS_INLINE: |
|
||||
{
|
||||
"AccessTokenJwtType": "JWT",
|
||||
"Discovery": {
|
||||
"ShowKeySet": true
|
||||
},
|
||||
"Authentication": {
|
||||
"CookieSameSiteMode": "Lax",
|
||||
"CheckSessionCookieSameSiteMode": "Lax"
|
||||
}
|
||||
}
|
||||
LOGIN_OPTIONS_INLINE: |
|
||||
{
|
||||
"AllowRememberLogin": false
|
||||
}
|
||||
LOGOUT_OPTIONS_INLINE: |
|
||||
{
|
||||
"AutomaticRedirectAfterSignOut": true
|
||||
}
|
||||
ASPNET_SERVICES_OPTIONS_INLINE: |
|
||||
{
|
||||
"ForwardedHeadersOptions": {
|
||||
"ForwardedHeaders" : "All"
|
||||
}
|
||||
}
|
||||
extends:
|
||||
file: docker-compose.prod.yml
|
||||
service: outline-oidc
|
||||
|
||||
outline-redis:
|
||||
container_name: outline-redis
|
||||
image: redis:7
|
||||
ports:
|
||||
- 10242:6379
|
||||
healthcheck:
|
||||
test: redis-cli ping
|
||||
interval: 10s
|
||||
timeout: 30s
|
||||
retries: 3
|
||||
extends:
|
||||
file: docker-compose.prod.yml
|
||||
service: outline-redis
|
||||
|
||||
outline-postgres:
|
||||
container_name: outline-postgres
|
||||
image: postgres:17
|
||||
ports:
|
||||
- 10243:5432
|
||||
volumes:
|
||||
- outline-postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: pg_isready
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
environment:
|
||||
POSTGRES_USER: outline
|
||||
POSTGRES_PASSWORD: outline
|
||||
POSTGRES_DB: outline
|
||||
extends:
|
||||
file: docker-compose.prod.yml
|
||||
service: outline-postgres
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
diff --git a/server/routes/index.ts b/server/routes/index.ts
|
||||
index 26fbded27..478de1922 100644
|
||||
--- a/server/routes/index.ts
|
||||
+++ b/server/routes/index.ts
|
||||
@@ -103,7 +103,7 @@ router.get("/locales/:lng.json", async (ctx) => {
|
||||
await send(ctx, path.join(lng, "translation.json"), {
|
||||
setHeaders: (res, _, stats) => {
|
||||
res.setHeader("Last-Modified", formatRFC7231(stats.mtime));
|
||||
- res.setHeader("Cache-Control", `public, max-age=${7 * Day.seconds}`);
|
||||
+ res.setHeader("Cache-Control", "no-store");
|
||||
res.setHeader(
|
||||
"ETag",
|
||||
crypto.createHash("md5").update(stats.mtime.toISOString()).digest("hex")
|
||||
diff --git a/vite.config.ts b/vite.config.ts
|
||||
index 32b52d44e..26d611fee 100644
|
||||
--- a/vite.config.ts
|
||||
+++ b/vite.config.ts
|
||||
@@ -45,6 +45,17 @@ export default () =>
|
||||
: { strict: true },
|
||||
},
|
||||
plugins: [
|
||||
+ {
|
||||
+ name: 'reload',
|
||||
+ configureServer(server) {
|
||||
+ const { ws, watcher } = server;
|
||||
+ watcher.on('change', file => {
|
||||
+ if (file.endsWith('build/shared/i18n/locales/ru_RU/translation.json')) {
|
||||
+ ws.send({ type: 'full-reload' });
|
||||
+ }
|
||||
+ });
|
||||
+ },
|
||||
+ },
|
||||
// https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme
|
||||
react({
|
||||
babel: {
|
||||
Reference in New Issue
Block a user