From 4448b86b93309a855f7a91e2347cb3b79c9cec40 Mon Sep 17 00:00:00 2001 From: The Mark Date: Sun, 23 Oct 2022 13:31:24 -0400 Subject: [PATCH 01/81] fix: Accept logged and not logged user in /base --- apps/api/src/routes/api/v1/base/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/api/src/routes/api/v1/base/index.ts b/apps/api/src/routes/api/v1/base/index.ts index 76854af8a..622a5aa4f 100644 --- a/apps/api/src/routes/api/v1/base/index.ts +++ b/apps/api/src/routes/api/v1/base/index.ts @@ -2,6 +2,14 @@ import { FastifyPluginAsync } from 'fastify'; import { errorHandler, listSettings, version } from '../../../../lib/common'; const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { + try { + return await request.jwtVerify(); + } catch(error){ + return {}; + } + }) + fastify.get('/', async (request) => { const teamId = request.user?.teamId; const settings = await listSettings() From dfd29dc37a8dd063216470f149d861616d05eb3d Mon Sep 17 00:00:00 2001 From: ThallesP Date: Tue, 25 Oct 2022 13:26:03 -0300 Subject: [PATCH 02/81] feature: initial support for specific git commit --- .vscode/settings.json | 21 +- apps/api/.env.example | 20 +- .../migration.sql | 2 + apps/api/prisma/schema.prisma | 1 + apps/api/src/jobs/deployApplication.ts | 3 + apps/api/src/lib/importers/github.ts | 4 +- .../routes/api/v1/applications/handlers.ts | 3 + .../src/routes/api/v1/applications/types.ts | 1 + .../src/routes/applications/[id]/index.svelte | 17 ++ pnpm-lock.yaml | 207 +++++++++++++----- 10 files changed, 209 insertions(+), 70 deletions(-) create mode 100644 apps/api/prisma/migrations/20221024204842_rollback_to_commit/migration.sql diff --git a/.vscode/settings.json b/.vscode/settings.json index 858d6ae2c..65a483d79 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,22 @@ { - "i18n-ally.localesPaths": ["src/lib/locales"], + "i18n-ally.localesPaths": [ + "src/lib/locales" + ], "i18n-ally.keystyle": "nested", "i18n-ally.extract.ignoredByFiles": { - "src\\routes\\__layout.svelte": ["Coolify", "coolLabs logo"] + "src\\routes\\__layout.svelte": [ + "Coolify", + "coolLabs logo" + ] }, "i18n-ally.sourceLanguage": "en", - "i18n-ally.enabledFrameworks": ["svelte"], - "i18n-ally.enabledParsers": ["js", "ts", "json"], + "i18n-ally.enabledFrameworks": [ + "svelte" + ], + "i18n-ally.enabledParsers": [ + "js", + "ts", + "json" + ], "i18n-ally.extract.autoDetect": true -} +} \ No newline at end of file diff --git a/apps/api/.env.example b/apps/api/.env.example index 800c40929..a36dfcac9 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -1,10 +1,10 @@ -COOLIFY_APP_ID=local-dev -# 32 bits long secret key -COOLIFY_SECRET_KEY=12341234123412341234123412341234 -COOLIFY_DATABASE_URL=file:../db/dev.db -COOLIFY_SENTRY_DSN= - -COOLIFY_IS_ON=docker -COOLIFY_WHITE_LABELED=false -COOLIFY_WHITE_LABELED_ICON= -COOLIFY_AUTO_UPDATE= \ No newline at end of file +COOLIFY_APP_ID=local-dev +# 32 bits long secret key +COOLIFY_SECRET_KEY=12341234123412341234123412341234 +COOLIFY_DATABASE_URL=file:../db/dev.db +COOLIFY_SENTRY_DSN= + +COOLIFY_IS_ON=docker +COOLIFY_WHITE_LABELED=false +COOLIFY_WHITE_LABELED_ICON= +COOLIFY_AUTO_UPDATE= diff --git a/apps/api/prisma/migrations/20221024204842_rollback_to_commit/migration.sql b/apps/api/prisma/migrations/20221024204842_rollback_to_commit/migration.sql new file mode 100644 index 000000000..aa8136ed8 --- /dev/null +++ b/apps/api/prisma/migrations/20221024204842_rollback_to_commit/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Application" ADD COLUMN "gitCommitHash" TEXT; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index d782bceae..19e2b3481 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -124,6 +124,7 @@ model Application { updatedAt DateTime @updatedAt destinationDockerId String? gitSourceId String? + gitCommitHash String? baseImage String? baseBuildImage String? gitSource GitSource? @relation(fields: [gitSourceId], references: [id]) diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index b2d2c8ec9..f31c54967 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -60,6 +60,7 @@ import * as buildpacks from '../lib/buildPacks'; gitSource, configHash, fqdn, + gitCommitHash, projectId, secrets, phpModules, @@ -160,6 +161,8 @@ import * as buildpacks from '../lib/buildPacks'; githubAppId: gitSource.githubApp?.id, gitlabAppId: gitSource.gitlabApp?.id, customPort: gitSource.customPort, + gitCommitHash: gitCommitHash, + configuration, repository, branch, buildId, diff --git a/apps/api/src/lib/importers/github.ts b/apps/api/src/lib/importers/github.ts index f42461939..8e62f442c 100644 --- a/apps/api/src/lib/importers/github.ts +++ b/apps/api/src/lib/importers/github.ts @@ -9,6 +9,7 @@ export default async function ({ githubAppId, repository, apiUrl, + gitCommitHash, htmlUrl, branch, buildId, @@ -20,6 +21,7 @@ export default async function ({ githubAppId: string; repository: string; apiUrl: string; + gitCommitHash?: string; htmlUrl: string; branch: string; buildId: string; @@ -36,7 +38,7 @@ export default async function ({ applicationId }); await asyncExecShell( - `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir} && git submodule update --init --recursive && git lfs pull && cd .. ` + `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir} && git checkout ${gitCommitHash} && git submodule update --init --recursive && git lfs pull && cd .. ` ); } else { diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index d179aabfa..e616aaa01 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -327,6 +327,7 @@ export async function saveApplication(request: FastifyRequest, dockerFileLocation, denoMainFile, denoOptions, + gitCommitHash, baseImage, baseBuildImage, deploymentType, @@ -365,6 +366,7 @@ export async function saveApplication(request: FastifyRequest, pythonVariable, denoOptions, baseImage, + gitCommitHash, baseBuildImage, deploymentType, dockerComposeFile, @@ -383,6 +385,7 @@ export async function saveApplication(request: FastifyRequest, exposePort, pythonWSGI, pythonModule, + gitCommitHash, pythonVariable, denoOptions, baseImage, diff --git a/apps/api/src/routes/api/v1/applications/types.ts b/apps/api/src/routes/api/v1/applications/types.ts index b282b0647..a11e6356d 100644 --- a/apps/api/src/routes/api/v1/applications/types.ts +++ b/apps/api/src/routes/api/v1/applications/types.ts @@ -19,6 +19,7 @@ export interface SaveApplication extends OnlyId { denoMainFile: string, denoOptions: string, baseImage: string, + gitCommitHash: string, baseBuildImage: string, deploymentType: string, baseDatabaseBranch: string, diff --git a/apps/ui/src/routes/applications/[id]/index.svelte b/apps/ui/src/routes/applications/[id]/index.svelte index acfe3c686..9113d7f8b 100644 --- a/apps/ui/src/routes/applications/[id]/index.svelte +++ b/apps/ui/src/routes/applications/[id]/index.svelte @@ -496,6 +496,23 @@ > {/if} +
+ + {#if isDisabled} + + {:else} + + {/if} +
{#if isDisabled || application.settings.isPublicRepository} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bac8b5276..ceea0a945 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: '@iarna/toml': 2.2.5 '@ladjs/graceful': 3.0.2 '@prisma/client': 4.4.0 - '@types/node': 18.7.23 + '@types/node': 18.8.5 '@types/node-os-utils': 1.3.0 '@typescript-eslint/eslint-plugin': 5.38.1 '@typescript-eslint/parser': 5.38.1 @@ -34,21 +34,21 @@ importers: bree: 9.1.2 cabin: 9.1.2 compare-versions: 5.0.1 - csv-parse: ^5.3.0 - csvtojson: ^2.0.10 + csv-parse: 5.3.1 + csvtojson: 2.0.10 cuid: 2.1.8 dayjs: 1.11.5 dockerode: 3.3.4 dotenv-extended: 2.9.0 esbuild: 0.15.10 - eslint: 8.23.0 + eslint: 8.25.0 eslint-config-prettier: 8.5.0 eslint-plugin-prettier: 4.2.1 execa: 6.1.0 - fastify: 4.7.0 + fastify: 4.8.1 fastify-plugin: 4.2.1 generate-password: 1.7.0 - got: 12.5.1 + got: 12.5.2 is-ip: 5.0.0 is-port-reachable: 4.0.0 js-yaml: 4.1.0 @@ -69,7 +69,7 @@ importers: typescript: 4.8.4 unique-names-generator: 4.7.1 dependencies: - '@breejs/ts-worker': 2.0.0_z4zw7clouxa3aqbp4be65jzeva + '@breejs/ts-worker': 2.0.0_f4ke2bigmcjyxrh5btaoi2b74i '@fastify/autoload': 5.4.0 '@fastify/cookie': 8.3.0 '@fastify/cors': 8.1.0 @@ -85,17 +85,17 @@ importers: bree: 9.1.2 cabin: 9.1.2 compare-versions: 5.0.1 - csv-parse: 5.3.0 + csv-parse: 5.3.1 csvtojson: 2.0.10 cuid: 2.1.8 dayjs: 1.11.5 dockerode: 3.3.4 dotenv-extended: 2.9.0 execa: 6.1.0 - fastify: 4.7.0 + fastify: 4.8.1 fastify-plugin: 4.2.1 generate-password: 1.7.0 - got: 12.5.1 + got: 12.5.2 is-ip: 5.0.0 is-port-reachable: 4.0.0 js-yaml: 4.1.0 @@ -111,14 +111,14 @@ importers: strip-ansi: 7.0.1 unique-names-generator: 4.7.1 devDependencies: - '@types/node': 18.7.23 + '@types/node': 18.8.5 '@types/node-os-utils': 1.3.0 - '@typescript-eslint/eslint-plugin': 5.38.1_pvy74qhkkcd5sngj4qereqoplm - '@typescript-eslint/parser': 5.38.1_nwctkcr5uyxf47tw7zkgamxmfq + '@typescript-eslint/eslint-plugin': 5.38.1_444tv3vqp6lpktlxqzfovoqee4 + '@typescript-eslint/parser': 5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q esbuild: 0.15.10 - eslint: 8.23.0 - eslint-config-prettier: 8.5.0_eslint@8.23.0 - eslint-plugin-prettier: 4.2.1_tgumt6uwl2md3n6uqnggd6wvce + eslint: 8.25.0 + eslint-config-prettier: 8.5.0_eslint@8.25.0 + eslint-plugin-prettier: 4.2.1_hvbqyfstm4urdpm6ffpwfka4e4 nodemon: 2.0.20 prettier: 2.7.1 rimraf: 3.0.2 @@ -208,7 +208,7 @@ importers: svelte: 3.50.0 svelte-check: 2.9.0_shxyscafa2tdzd4z2tgnnrhyyu svelte-preprocess: 4.10.7_gzukngxpmlbzkiu3cz7vpamp3y - tailwindcss: 3.1.8_postcss@8.4.16 + tailwindcss: 3.1.8 tailwindcss-scrollbar: 0.1.0_tailwindcss@3.1.8 tslib: 2.4.0 typescript: 4.8.2 @@ -253,15 +253,14 @@ packages: engines: {node: '>= 10'} dev: false - /@breejs/ts-worker/2.0.0_z4zw7clouxa3aqbp4be65jzeva: + /@breejs/ts-worker/2.0.0_f4ke2bigmcjyxrh5btaoi2b74i: resolution: {integrity: sha512-6anHRcmgYlF7mrm/YVRn6rx2cegLuiY3VBxkkimOTWC/dVQeH336imVSuIKEGKTwiuNTPr2hswVdDSneNuXg3A==} engines: {node: '>= 12.11'} peerDependencies: bree: '>=9.0.0' - tsconfig-paths: '>= 4' dependencies: bree: 9.1.2 - ts-node: 10.8.2_gbhfbbeqrol7fxixnzbkbuanxe + ts-node: 10.8.2_ptpocrdt7oaz4ni5mlvucph5pa tsconfig-paths: 4.1.0 transitivePeerDependencies: - '@swc/core' @@ -312,6 +311,23 @@ packages: - supports-color dev: true + /@eslint/eslintrc/1.3.3: + resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.4.0 + globals: 13.15.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@fastify/accept-negotiator/1.0.0: resolution: {integrity: sha512-4R/N2KfYeld7A5LGkai+iUFMahXcxxYbDp+XS2B1yuL3cdmZLJ9TlCnNzT3q5xFTqsYm0GPpinLUwfSwjcVjyA==} engines: {node: '>=14'} @@ -431,6 +447,17 @@ packages: - supports-color dev: true + /@humanwhocodes/config-array/0.10.7: + resolution: {integrity: sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + /@humanwhocodes/gitignore-to-minimatch/1.0.2: resolution: {integrity: sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==} dev: true @@ -626,7 +653,7 @@ packages: lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.1.8_postcss@8.4.16 + tailwindcss: 3.1.8 dev: false /@tsconfig/node10/1.0.8: @@ -690,6 +717,10 @@ packages: /@types/node/18.7.23: resolution: {integrity: sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==} + dev: true + + /@types/node/18.8.5: + resolution: {integrity: sha512-Bq7G3AErwe5A/Zki5fdD3O6+0zDChhg671NfPjtIcbtzDNZTv4NPKMRFr7gtYPG7y+B8uTiNK4Ngd9T0FTar6Q==} /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -738,7 +769,7 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin/5.38.1_pvy74qhkkcd5sngj4qereqoplm: + /@typescript-eslint/eslint-plugin/5.38.1_444tv3vqp6lpktlxqzfovoqee4: resolution: {integrity: sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -749,12 +780,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.38.1_nwctkcr5uyxf47tw7zkgamxmfq + '@typescript-eslint/parser': 5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q '@typescript-eslint/scope-manager': 5.38.1 - '@typescript-eslint/type-utils': 5.38.1_nwctkcr5uyxf47tw7zkgamxmfq - '@typescript-eslint/utils': 5.38.1_nwctkcr5uyxf47tw7zkgamxmfq + '@typescript-eslint/type-utils': 5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q + '@typescript-eslint/utils': 5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q debug: 4.3.4 - eslint: 8.23.0 + eslint: 8.25.0 ignore: 5.2.0 regexpp: 3.2.0 semver: 7.3.7 @@ -784,7 +815,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.38.1_nwctkcr5uyxf47tw7zkgamxmfq: + /@typescript-eslint/parser/5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q: resolution: {integrity: sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -798,7 +829,7 @@ packages: '@typescript-eslint/types': 5.38.1 '@typescript-eslint/typescript-estree': 5.38.1_typescript@4.8.4 debug: 4.3.4 - eslint: 8.23.0 + eslint: 8.25.0 typescript: 4.8.4 transitivePeerDependencies: - supports-color @@ -840,7 +871,7 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils/5.38.1_nwctkcr5uyxf47tw7zkgamxmfq: + /@typescript-eslint/type-utils/5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q: resolution: {integrity: sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -851,9 +882,9 @@ packages: optional: true dependencies: '@typescript-eslint/typescript-estree': 5.38.1_typescript@4.8.4 - '@typescript-eslint/utils': 5.38.1_nwctkcr5uyxf47tw7zkgamxmfq + '@typescript-eslint/utils': 5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q debug: 4.3.4 - eslint: 8.23.0 + eslint: 8.25.0 tsutils: 3.21.0_typescript@4.8.4 typescript: 4.8.4 transitivePeerDependencies: @@ -930,7 +961,7 @@ packages: - typescript dev: true - /@typescript-eslint/utils/5.38.1_nwctkcr5uyxf47tw7zkgamxmfq: + /@typescript-eslint/utils/5.38.1_z4bbprzjrhnsfa24uvmcbu7f5q: resolution: {integrity: sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -940,9 +971,9 @@ packages: '@typescript-eslint/scope-manager': 5.38.1 '@typescript-eslint/types': 5.38.1 '@typescript-eslint/typescript-estree': 5.38.1_typescript@4.8.4 - eslint: 8.23.0 + eslint: 8.25.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.23.0 + eslint-utils: 3.0.0_eslint@8.25.0 transitivePeerDependencies: - supports-color - typescript @@ -2359,8 +2390,8 @@ packages: engines: {node: '>=4'} hasBin: true - /csv-parse/5.3.0: - resolution: {integrity: sha512-UXJCGwvJ2fep39purtAn27OUYmxB1JQto+zhZ4QlJpzsirtSFbzLvip1aIgziqNdZp/TptvsKEV5BZSxe10/DQ==} + /csv-parse/5.3.1: + resolution: {integrity: sha512-R4Hv6eGJNzgcKdThZ6XORbSQ873HVcNke74QIq+LbwpT90LaZ8Xzl7KKiuIP16xq/P7ofzRt0h7S0xm+fVScsw==} dev: false /csvtojson/2.0.10: @@ -2392,7 +2423,7 @@ packages: css-selector-tokenizer: 0.8.0 postcss: 8.4.16 postcss-js: 4.0.0_postcss@8.4.16 - tailwindcss: 3.1.8_postcss@8.4.16 + tailwindcss: 3.1.8 transitivePeerDependencies: - ts-node dev: false @@ -2954,7 +2985,16 @@ packages: eslint: 8.23.0 dev: true - /eslint-plugin-prettier/4.2.1_tgumt6uwl2md3n6uqnggd6wvce: + /eslint-config-prettier/8.5.0_eslint@8.25.0: + resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.25.0 + dev: true + + /eslint-plugin-prettier/4.2.1_hvbqyfstm4urdpm6ffpwfka4e4: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2965,8 +3005,8 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.23.0 - eslint-config-prettier: 8.5.0_eslint@8.23.0 + eslint: 8.25.0 + eslint-config-prettier: 8.5.0_eslint@8.25.0 prettier: 2.7.1 prettier-linter-helpers: 1.0.0 dev: true @@ -3007,6 +3047,16 @@ packages: eslint-visitor-keys: 2.1.0 dev: true + /eslint-utils/3.0.0_eslint@8.25.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.25.0 + eslint-visitor-keys: 2.1.0 + dev: true + /eslint-visitor-keys/2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} @@ -3065,6 +3115,53 @@ packages: - supports-color dev: true + /eslint/8.25.0: + resolution: {integrity: sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.3.3 + '@humanwhocodes/config-array': 0.10.7 + '@humanwhocodes/module-importer': 1.0.1 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.25.0 + eslint-visitor-keys: 3.3.0 + espree: 9.4.0 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.15.0 + globby: 11.1.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-sdsl: 4.1.5 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + /espree/9.4.0: resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3224,15 +3321,15 @@ packages: resolution: {integrity: sha512-dlGKiwLzRBKkEf5J5ho0uAD/Jdv8GQVUbriB3tAX3ehRUXE4gTV3lRd5inEg9li1aLzb0EGj8y2K4/8g1TN06g==} dev: false - /fastify/4.7.0: - resolution: {integrity: sha512-FK3WT6arZOd2Fm696vIn90DOFr1f8QZbFcvUzYRPJTBV0pzm1xN8Y3n9yegtv1ajAxpdTwuLhB10Wwb/ptMRqQ==} + /fastify/4.8.1: + resolution: {integrity: sha512-3an6yyXg7j5XPHTRxgFqUwIRaJPR7F8OPR8Uboo0SIgHx1orOqc9Y8Sl5Kz8+xK7JCy3c3mfRujskDjMu/nFfA==} dependencies: '@fastify/ajv-compiler': 3.3.1 '@fastify/error': 3.0.0 '@fastify/fast-json-stringify-compiler': 4.1.0 abstract-logging: 2.0.1 avvio: 8.2.0 - find-my-way: 7.2.0 + find-my-way: 7.3.1 light-my-request: 5.6.1 pino: 8.6.1 process-warning: 2.0.0 @@ -3295,8 +3392,8 @@ packages: dependencies: to-regex-range: 5.0.1 - /find-my-way/7.2.0: - resolution: {integrity: sha512-27SFA5sSYDYFZCQ/7SSJB0yhStTP/qxKP1OEC8feZvkHFRuD3fGcQ97Y+0w8HpKTDfMYWXGU3h2ETRGt5zPWyA==} + /find-my-way/7.3.1: + resolution: {integrity: sha512-kGvM08SOkqvheLcuQ8GW9t/H901Qb9rZEbcNWbXopzy4jDRoaJpJoObPSKf4MnQLZ20ZTp7rL5MpF6rf+pqmyg==} engines: {node: '>=14'} dependencies: fast-deep-equal: 3.1.3 @@ -3590,8 +3687,8 @@ packages: responselike: 2.0.0 dev: false - /got/12.5.1: - resolution: {integrity: sha512-sD16AK8cCyUoPtKr/NMvLTFFa+T3i3S+zoiuvhq0HP2YiqBZA9AtlBjAdsQBsLBK7slPuvmfE0OxhGi7N5dD4w==} + /got/12.5.2: + resolution: {integrity: sha512-guHGMSEcsA5m1oPRweXUJnug0vuvlkX9wx5hzOka+ZBrBUOJHU0Z1JcNu3QE5IPGnA5aXUsQHdWOD4eJg9/v3A==} engines: {node: '>=14.16'} dependencies: '@sindresorhus/is': 5.3.0 @@ -4031,6 +4128,10 @@ packages: engines: {node: '>=12'} dev: false + /js-sdsl/4.1.5: + resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} + dev: true + /js-tokens/3.0.2: resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} dev: true @@ -5118,7 +5219,7 @@ packages: dependencies: aggregate-error: 4.0.1 dns-socket: 4.2.2 - got: 12.5.1 + got: 12.5.2 is-ip: 4.0.0 dev: false @@ -5975,15 +6076,13 @@ packages: peerDependencies: tailwindcss: '>= 2.x.x' dependencies: - tailwindcss: 3.1.8_postcss@8.4.16 + tailwindcss: 3.1.8 dev: true - /tailwindcss/3.1.8_postcss@8.4.16: + /tailwindcss/3.1.8: resolution: {integrity: sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==} engines: {node: '>=12.13.0'} hasBin: true - peerDependencies: - postcss: ^8.0.9 dependencies: arg: 5.0.2 chokidar: 3.5.3 @@ -6106,7 +6205,7 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ts-node/10.8.2_gbhfbbeqrol7fxixnzbkbuanxe: + /ts-node/10.8.2_ptpocrdt7oaz4ni5mlvucph5pa: resolution: {integrity: sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==} hasBin: true peerDependencies: @@ -6125,7 +6224,7 @@ packages: '@tsconfig/node12': 1.0.9 '@tsconfig/node14': 1.0.1 '@tsconfig/node16': 1.0.2 - '@types/node': 18.7.23 + '@types/node': 18.8.5 acorn: 8.8.0 acorn-walk: 8.2.0 arg: 4.1.3 From e038865693eaac2b90e7295c212a32b56b031d65 Mon Sep 17 00:00:00 2001 From: ThallesP Date: Tue, 25 Oct 2022 13:51:10 -0300 Subject: [PATCH 03/81] feature: add default to latest commit and support for gitlab --- apps/api/src/lib/importers/github.ts | 4 ++-- apps/api/src/lib/importers/gitlab.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/api/src/lib/importers/github.ts b/apps/api/src/lib/importers/github.ts index 8e62f442c..f310c4704 100644 --- a/apps/api/src/lib/importers/github.ts +++ b/apps/api/src/lib/importers/github.ts @@ -38,7 +38,7 @@ export default async function ({ applicationId }); await asyncExecShell( - `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir} && git checkout ${gitCommitHash} && git submodule update --init --recursive && git lfs pull && cd .. ` + `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir} && git checkout ${gitCommitHash || "-"} && git submodule update --init --recursive && git lfs pull && cd .. ` ); } else { @@ -69,7 +69,7 @@ export default async function ({ applicationId }); await asyncExecShell( - `git clone -q -b ${branch} https://x-access-token:${token}@${url}/${repository}.git --config core.sshCommand="ssh -p ${customPort}" ${workdir}/ && cd ${workdir} && git submodule update --init --recursive && git lfs pull && cd .. ` + `git clone -q -b ${branch} https://x-access-token:${token}@${url}/${repository}.git --config core.sshCommand="ssh -p ${customPort}" ${workdir}/ && cd ${workdir} && git checkout ${gitCommitHash || "-"} && git submodule update --init --recursive && git lfs pull && cd .. ` ); } const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`); diff --git a/apps/api/src/lib/importers/gitlab.ts b/apps/api/src/lib/importers/gitlab.ts index 35fa3d8ce..051e2a9d7 100644 --- a/apps/api/src/lib/importers/gitlab.ts +++ b/apps/api/src/lib/importers/gitlab.ts @@ -6,6 +6,7 @@ export default async function ({ workdir, repodir, htmlUrl, + gitCommitHash, repository, branch, buildId, @@ -20,6 +21,7 @@ export default async function ({ branch: string; buildId: string; repodir: string; + gitCommitHash: string; privateSshKey: string; customPort: number; forPublic: boolean; @@ -40,11 +42,11 @@ export default async function ({ if (forPublic) { await asyncExecShell( - `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. ` + `git clone -q -b ${branch} https://${url}/${repository}.git ${workdir}/ && cd ${workdir}/ && git checkout ${gitCommitHash || "-"} && git submodule update --init --recursive && git lfs pull && cd .. ` ); } else { await asyncExecShell( - `git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -p ${customPort} -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. ` + `git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -p ${customPort} -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git checkout ${gitCommitHash || "-"} && git submodule update --init --recursive && git lfs pull && cd .. ` ); } From 733de60f7ca853f5c2789bae38d7e8725ba41456 Mon Sep 17 00:00:00 2001 From: Gabriel Engel Date: Wed, 9 Nov 2022 19:27:03 -0300 Subject: [PATCH 04/81] Starting translations work --- README.md | 25 +- .../ui/src/lib/components/LocalePicker.svelte | 11 + apps/ui/src/lib/lang.json | 3 + apps/ui/src/lib/locales/es.json | 341 ++++++++++++++++++ apps/ui/src/lib/locales/ko.json | 341 ++++++++++++++++++ apps/ui/src/lib/locales/pt.json | 341 ++++++++++++++++++ apps/ui/src/lib/translations.ts | 24 +- apps/ui/src/routes/__layout.svelte | 27 +- docs/contribution/Translating.md | 61 ++++ 9 files changed, 1160 insertions(+), 14 deletions(-) create mode 100644 apps/ui/src/lib/components/LocalePicker.svelte create mode 100644 apps/ui/src/lib/locales/es.json create mode 100644 apps/ui/src/lib/locales/ko.json create mode 100644 apps/ui/src/lib/locales/pt.json create mode 100644 docs/contribution/Translating.md diff --git a/README.md b/README.md index a2fa60c87..433c06519 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Deploy your resource to: ### Services + - [Appwrite](https://appwrite.io) - [WordPress](https://docs.coollabs.io/coolify/services/wordpress) - [Ghost](https://ghost.org) @@ -105,11 +106,29 @@ A fresh installation is necessary. v2 and v3 are not compatible with v1. - Email: [andras@coollabs.io](mailto:andras@coollabs.io) - Discord: [Invitation](https://coollabs.io/discord) -## Development Contributions +--- -Coolify is developed under the Apache License and you can help to make it grow → [Start coding!](./CONTRIBUTION.md) +## ⚗️ Expertise Contributions -## Financial Contributors +Coolify is developed under the [Apache License](./LICENSE) and you can help to make it grow. +Our community will be glad to have you on board! + +Learn how to contribute to Coolify as as ... + +→ [👩🏾‍💻 Software developer](./CONTRIBUTION.md) + +→ [🧑🏻‍🏫 Translator](./docs/contribution/Translating.md) + + + +--- + +## 💰 Financial Contributors Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/coollabsio/contribute)] diff --git a/apps/ui/src/lib/components/LocalePicker.svelte b/apps/ui/src/lib/components/LocalePicker.svelte new file mode 100644 index 000000000..dfd004165 --- /dev/null +++ b/apps/ui/src/lib/components/LocalePicker.svelte @@ -0,0 +1,11 @@ + + +
+ +
\ No newline at end of file diff --git a/apps/ui/src/lib/lang.json b/apps/ui/src/lib/lang.json index fdfc5bf80..f5485ece0 100644 --- a/apps/ui/src/lib/lang.json +++ b/apps/ui/src/lib/lang.json @@ -1,4 +1,7 @@ { "fr": "Français", + "pt": "Português", + "es": "Espanhol", + "ko": "Korean", "en": "English" } diff --git a/apps/ui/src/lib/locales/es.json b/apps/ui/src/lib/locales/es.json new file mode 100644 index 000000000..54eb5f716 --- /dev/null +++ b/apps/ui/src/lib/locales/es.json @@ -0,0 +1,341 @@ +{ + "layout":{ + "update_done":"Actualización completada.", + "wait_new_version_startup":"Esperando que comience la nueva versión.", + "new_version":"Nueva versión accesible. Recargando.", + "switch_to_a_different_team":"Cambia a otro equipo.", + "update_available":"Actualización disponible" + }, + "error":{ + "you_can_find_your_way_back":"Puedes encontrar tu camino de vuelta", + "here":"Aquí.", + "you_are_lost":"¡Estás perdido! ¡Pero no tengas miedo!" + }, + "index":{ + "dashboard":"Dashboard", + "applications":"Aplicaciones", + "destinations":"Destinos", + "git_sources":"Fuentes Git", + "databases":"Bases de datos", + "services":"Servicios", + "teams":"Equipos", + "not_implemented_yet":"Aún no se ha aplicado", + "database":"Base de datos", + "settings":"Ajustes", + "global_settings":"Ajustes mundiales", + "secret":"Secret", + "team":"Equipo", + "logout":"Cerrar sesión" + }, + "login":{ + "already_logged_in":"Ya se ha registrado.", + "authenticating":"Autenticando.", + "login":"Iniciar sesión" + }, + "forms":{ + "password":"Contraseña", + "email":"Dirección de correo electrónico", + "passwords_not_match":"Las contraseñas no coinciden.", + "password_again":"Contraseña de nuevo", + "save":"Guardar", + "saving":"Salvando.", + "name":"Nombre", + "value":"Valor", + "action":"Acciones", + "is_required":"es necesario.", + "add":"Añadir", + "set":"Set", + "remove":"Retirar", + "path":"Camino", + "confirm_continue":"¿Estás seguro de continuar?", + "must_be_stopped_to_modify":"Debe ser detenido para modificar.", + "port":"Puerto", + "default":"Por defecto", + "base_directory":"Base Directory", + "publish_directory":"Publish Directory", + "generated_automatically_after_start":"Generado automáticamente después del inicio", + "roots_password":"La contraseña de Root", + "root_user":"Usuario raíz", + "eg":"eg", + "user":"Usuario", + "loading":"Carga.", + "version":"Versión", + "host":"Host", + "already_used_for":"##########################################################################################################################################################################################################################################################", + "configuration":"Configuración", + "engine":"Motor", + "network":"Red", + "ip_address":"Dirección IP", + "ssh_private_key":"SSH Clave privada", + "type":"Tipo", + "html_url":"URL", + "api_url":"API", + "organization":"Organización", + "new_password":"Nueva contraseña", + "super_secure_new_password":"Super seguro nueva contraseña", + "submit":"Submit", + "default_email_address":"Dirección de correo electrónico predeterminada", + "default_password":"Contraseña predeterminada", + "username":"Nombre de usuario", + "root_db_user":"Root DB Usuario", + "root_db_password":"Root DB Contraseña", + "api_port":"API Port", + "verifying":"Verificación", + "verify_emails_without_smtp":"Verificar correos electrónicos sin SMTP", + "extra_config":"Extra Config", + "select_a_service":"Seleccione un Servicio", + "select_a_service_version":"Seleccione una versión de servicio", + "removing":"Retirándose.", + "remove_domain":"Eliminar el dominio", + "public_port_range":"Public Port Range", + "public_port_range_explainer":"Puertos utilizados para exponer bases de datos/servicios/servicios internos. Añádalos a su cortafuegos (si es aplicable).Seguido se indicará una gama de puertos, por ejemplo: tachuelas clase='text-settings '9000-9100 seg/span", + "no_actions_available":"No se dispone de medidas", + "admin_api_key":"Clave de API de Admin" + }, + "register":{ + "register":"Registro", + "registering":"Registro.", + "first_user":"Está registrando al primer usuario. Será el administrador de tu instancia de Coolify." + }, + "reset":{ + "reset_password":"Reset", + "invalid_secret_key":"Una llave secreta inválida.", + "secret_key":"Secret Key", + "find_path_secret_key":"Puedes encontrarlo en ~coolify/.env (COOLIFY_SECRET_KEY)" + }, + "application":{ + "configuration":{ + "buildpack":{ + "choose_this_one":"Elige esta." + }, + "branch_already_in_use":"Esta rama ya es utilizada por otra aplicación. Webhooks no funcionará en este caso para ambas aplicaciones. ¿Seguro que quieres usarlo?", + "no_repositories_configured":"No hay repositorios configurados para su aplicación Git.", + "configure_it_now":"Configure ahora", + "loading_repositories":"Carga de repositorios ...", + "select_a_repository":"Seleccione un repositorio", + "loading_branches":"Cargando ramas ...", + "select_a_repository_first":"Por favor seleccione un repositorio primero", + "select_a_branch":"Por favor seleccione una rama", + "loading_groups":"Grupos de carga.", + "select_a_group":"Seleccione un grupo", + "loading_projects":"Cargando proyectos.", + "select_a_project":"Seleccione un proyecto", + "no_projects_found":"No se han encontrado proyectos", + "no_branches_found":"No hay ramas encontradas", + "configure_build_pack":"Configure Build Pack", + "scanning_repository_suggest_build_pack":"Repositorio de exploración para sugerir un paquete de construcción para usted.", + "found_lock_file":"encontrado archivo de bloqueo para {{packageManager}}.Seguido de comandos predefinidos.", + "configure_destination":"Configurar Destino", + "no_configurable_destination":"No hay destino configurable encontrado", + "select_a_repository_project":"Seleccione un Repositorio / Proyecto", + "select_a_git_source":"Seleccione una fuente de Git", + "no_configurable_git":"No se encontró una fuente de Git configurable", + "configuration_missing":"Falta de configuración" + }, + "build":{ + "queued_waiting_exec":"Queued and waiting for execution.", + "build_logs_of":"Construir registros de", + "running":"Corriendo", + "queued":"Queued", + "finished_in":"Terminado en", + "load_more":"Carga más", + "no_logs":"No hay registros encontrados", + "waiting_logs":"Esperando los registros." + }, + "preview":{ + "need_during_buildtime":"¿Necesitas durante el tiempo de construcción?", + "setup_secret_app_first":"Puede añadir secretos a las implementaciones PR/MR. Por favor, agregue secretos a la aplicación primero. √≠br]Useful for creating יspan class='text-settings 'staging won/span environments.", + "values_overwriting_app_secrets":"Estos valores sobrescriben los secretos de aplicación en las implementaciones PR/MR. Útil para la creación de clase 0'text-settings 'estaging significan ambientes / paño.", + "redeploy":"Redistribución", + "no_previews_available":"No hay vistas previas disponibles" + }, + "secrets":{ + "secret_saved":"Secreto salvado.", + "use_isbuildsecret":"Use isBuildSecret", + "secrets_for":"Secretos para" + }, + "storage":{ + "path_is_required":"Se requiere camino.", + "storage_saved":"Almacenamiento guardado.", + "storage_updated":"Almacenamiento actualizado.", + "storage_deleted":"Almacenamiento eliminado.", + "persistent_storage_explainer":"Puede especificar cualquier carpeta que desee ser persistente a través de las implementaciones.Seguido de la clase='text-settings 'ejemplo observado/span significa que preservará {{type}}이(가) 이미 사용됨", + "configuration":"구성", + "engine":"엔진", + "network":"회로망", + "ip_address":"IP 주소", + "ssh_private_key":"SSH 개인 키", + "type":"유형", + "html_url":"HTML URL", + "api_url":"API URL", + "organization":"조직", + "new_password":"새 비밀번호", + "super_secure_new_password":"매우 안전한 새 비밀번호", + "submit":"제출하다", + "default_email_address":"기본 이메일 주소", + "default_password":"기본 비밀번호", + "username":"사용자 이름", + "root_db_user":"루트 DB 사용자", + "root_db_password":"루트 DB 비밀번호", + "api_port":"API 포트", + "verifying":"확인 중", + "verify_emails_without_smtp":"SMTP 없이 이메일 확인", + "extra_config":"추가 구성", + "select_a_service":"서비스 선택", + "select_a_service_version":"서비스 버전 선택", + "removing":"풀이...", + "remove_domain":"도메인 제거", + "public_port_range":"공용 포트 범위", + "public_port_range_explainer":"데이터베이스/서비스/내부 서비스를 노출하는 데 사용되는 포트입니다.
방화벽에 추가합니다(해당되는 경우).

포트 범위를 지정할 수 있습니다(예: ). 9000-9100", + "no_actions_available":"사용 가능한 작업이 없습니다.", + "admin_api_key":"관리 API 키" + }, + "register":{ + "register":"등록하다", + "registering":"등록 중...", + "first_user":"첫 번째 사용자를 등록하고 있습니다. Coolify 인스턴스의 관리자가 됩니다." + }, + "reset":{ + "reset_password":"초기화", + "invalid_secret_key":"잘못된 비밀 키입니다.", + "secret_key":"비밀 키", + "find_path_secret_key":"~/coolify/.env(COOLIFY_SECRET_KEY)에서 찾을 수 있습니다." + }, + "application":{ + "configuration":{ + "buildpack":{ + "choose_this_one":"이걸 선택..." + }, + "branch_already_in_use":"이 분기는 이미 다른 응용 프로그램에서 사용하고 있습니다. 이 경우 두 애플리케이션 모두에 대해 Webhook이 작동하지 않습니다. 사용하시겠습니까?", + "no_repositories_configured":"Git 애플리케이션에 대해 구성된 저장소가 없습니다.", + "configure_it_now":"지금 구성", + "loading_repositories":"저장소 로드 중...", + "select_a_repository":"저장소를 선택하십시오", + "loading_branches":"브랜치 로드 중...", + "select_a_repository_first":"먼저 저장소를 선택하십시오", + "select_a_branch":"지점을 선택해 주세요", + "loading_groups":"그룹 로드 중...", + "select_a_group":"그룹을 선택하세요.", + "loading_projects":"프로젝트 로드 중...", + "select_a_project":"프로젝트를 선택하세요.", + "no_projects_found":"프로젝트를 찾을 수 없습니다.", + "no_branches_found":"지점을 찾을 수 없습니다", + "configure_build_pack":"빌드 팩 구성", + "scanning_repository_suggest_build_pack":"빌드 팩을 제안하기 위해 저장소를 검색하는 중...", + "found_lock_file":"{{packageManager}}에 대한 잠금 파일을 찾았습니다.
사전 정의된 명령 명령에 사용합니다.", + "configure_destination":"대상 구성", + "no_configurable_destination":"구성 가능한 대상을 찾을 수 없습니다.", + "select_a_repository_project":"리포지토리/프로젝트 선택", + "select_a_git_source":"Git 소스 선택", + "no_configurable_git":"구성 가능한 Git 소스를 찾을 수 없습니다.", + "configuration_missing":"구성 누락" + }, + "build":{ + "queued_waiting_exec":"큐에 넣고 실행을 기다리고 있습니다.", + "build_logs_of":"빌드 로그", + "running":"달리기", + "queued":"대기 중", + "finished_in":"완료", + "load_more":"더 찾아보기", + "no_logs":"로그를 찾을 수 없습니다.", + "waiting_logs":"로그를 기다리는 중..." + }, + "preview":{ + "need_during_buildtime":"빌드 시간에 필요하십니까?", + "setup_secret_app_first":"PR/MR 배포에 비밀을 추가할 수 있습니다. 먼저 응용 프로그램에 비밀을 추가하십시오.
스테이징 환경을 만드는 데 유용합니다.", + "values_overwriting_app_secrets":"이러한 값은 PR/MR 배포에서 애플리케이션 비밀을 덮어씁니다. 스테이징 환경을 만드는 데 유용합니다.", + "redeploy":"재배포", + "no_previews_available":"사용 가능한 미리보기가 없습니다." + }, + "secrets":{ + "secret_saved":"비밀이 저장되었습니다.", + "use_isbuildsecret":"isBuildSecret 사용", + "secrets_for":"비밀" + }, + "storage":{ + "path_is_required":"경로는 필수 항목입니다.", + "storage_saved":"저장용량이 저장되었습니다.", + "storage_updated":"스토리지가 업데이트되었습니다.", + "storage_deleted":"스토리지가 삭제되었습니다.", + "persistent_storage_explainer":"배포 간에 유지하려는 모든 폴더를 지정할 수 있습니다.
/example/app/를 보존함을 의미합니다. /app과 같은 컨테이너의 example은 애플리케이션의 루트 디렉토리입니다.

데이터베이스(SQLite) 또는 캐시와 같은 데이터를 저장하는 데 유용합니다." + }, + "deployment_queued":"배포가 대기 중입니다.", + "confirm_to_delete":"'{{name}}'을(를) 삭제하시겠습니까?", + "stop_application":"애플리케이션 중지", + "permission_denied_stop_application":"애플리케이션을 중지할 권한이 없습니다.", + "rebuild_application":"애플리케이션 재구축", + "permission_denied_rebuild_application":"애플리케이션을 다시 빌드할 권한이 없습니다.", + "build_and_start_application":"배포", + "permission_denied_build_and_start_application":"애플리케이션을 배포할 권한이 없습니다.", + "configurations":"구성", + "secret":"비밀", + "persistent_storage":"영구 스토리지", + "previews":"미리보기", + "logs":"애플리케이션 로그", + "build_logs":"빌드 로그", + "delete_application":"삭제", + "permission_denied_delete_application":"이 애플리케이션을 삭제할 권한이 없습니다.", + "domain_already_in_use":"도메인 {{domain}}은(는) 이미 사용 중입니다.", + "dns_not_set_error":"DNS가 올바르게 설정되지 않았거나 {{domain}}에 대해 전파되었습니다.

DNS 설정을 확인하십시오.", + "domain_required":"도메인은 필수 항목입니다.", + "settings_saved":"구성이 저장되었습니다.", + "dns_not_set_partial_error":"DNS가 설정되지 않았습니다.", + "domain_not_valid":"도메인을 확인할 수 없거나 서버 IP 주소를 가리키지 않습니다.

DNS 구성을 확인하고 다시 시도하십시오.", + "git_source":"힘내 소스", + "git_repository":"Git 저장소", + "build_pack":"빌드 팩", + "base_image":"배포 이미지", + "base_image_explainer":"배포에 사용할 이미지입니다.", + "base_build_image":"빌드 이미지", + "base_build_image_explainer":"빌드 프로세스 중에 사용될 이미지입니다.", + "destination":"목적지", + "application":"신청", + "url_fqdn":"URL(FQDN)", + "domain_fqdn":"도메인(FQDN)", + "https_explainer":"https를 지정하면 https를 통해서만 애플리케이션에 액세스할 수 있습니다. SSL 인증서가 생성됩니다.
www를 지정하면 애플리케이션이 www가 아닌 ​​곳에서 리디렉션(302)되거나 그 반대의 경우도 마찬가지입니다.
< br>도메인을 수정하려면 먼저 애플리케이션을 중지해야 합니다.

미리 DNS가 서버 IP를 가리키도록 설정해야 합니다.", + "ssl_www_and_non_www":"www 및 www가 없는 SSL을 생성하시겠습니까?", + "ssl_explainer":"www 및 non-www 모두에 대한 인증서를 생성합니다.
미리 두 DNS 항목을 설정해야 합니다.

두 DNS 항목 모두에 방문자가 있을 것으로 예상되는 경우 유용합니다.", + "install_command":"설치 명령", + "build_command":"빌드 명령", + "start_command":"시작 명령", + "directory_to_use_explainer":"모든 명령의 기반으로 사용할 디렉토리입니다.
monorepos와 함께 유용할 수 있습니다.", + "publish_directory_explainer":"배포를 위한 모든 자산이 포함된 디렉터리입니다.
예: dist,_site 또는 public< /스팬>.", + "features":"특징", + "enable_automatic_deployment":"자동 배포 활성화", + "enable_auto_deploy_webhooks":"웹훅을 통한 자동 배포를 활성화합니다.", + "enable_mr_pr_previews":"MR/PR 미리보기 활성화", + "expose_a_port":"포트 노출", + "enable_preview_deploy_mr_pr_requests":"끌어오기 또는 병합 요청에서 미리보기 배포를 활성화합니다.", + "debug_logs":"디버그 로그", + "enable_debug_log_during_build":"빌드 단계에서 디버그 로그를 활성화합니다.
민감한 정보가 표시되고 로그에 저장될 수 있습니다.", + "cant_activate_auto_deploy_without_repo":"이 리포지토리/분기에 대해 하나의 애플리케이션만 정의될 때까지 자동 배포를 활성화할 수 없습니다.", + "no_applications_found":"애플리케이션을 찾을 수 없습니다.", + "secret__batch_dot_env":".env 파일 붙여넣기", + "batch_secrets":"일괄 추가 비밀" + }, + "general":"일반적인", + "database":{ + "default_database":"기본 데이터베이스", + "generated_automatically_after_set_to_public":"public으로 설정 후 자동 생성", + "connection_string":"연결 문자열", + "set_public":"공개 설정", + "warning_database_public":"인터넷을 통해 데이터베이스에 연결할 수 있습니다.
이 경우 보안을 심각하게 생각하십시오!", + "change_append_only_mode":"추가 전용 모드 변경", + "warning_append_only":"백업에서 redis 데이터를 복원하려는 경우에 유용합니다.
데이터베이스를 다시 시작해야 합니다.", + "select_database_type":"데이터베이스 유형 선택", + "select_database_version":"데이터베이스 버전 선택", + "confirm_stop":"{{name}}을(를) 중지하시겠습니까?", + "stop_database":"중지", + "permission_denied_stop_database":"데이터베이스를 중지할 권한이 없습니다.", + "start_database":"시작", + "permission_denied_start_database":"데이터베이스를 시작할 권한이 없습니다.", + "delete_database":"삭제", + "permission_denied_delete_database":"데이터베이스를 삭제할 권한이 없습니다.", + "no_databases_found":"데이터베이스를 찾을 수 없습니다.", + "logs":"로그" + }, + "destination":{ + "delete_destination":"삭제", + "permission_denied_delete_destination":"이 목적지를 삭제할 권한이 없습니다.", + "add_to_coolify":"Coolify에 추가", + "coolify_proxy_stopped":"Coolify 프록시가 중지되었습니다!", + "coolify_proxy_started":"Coolify 프록시가 시작되었습니다!", + "confirm_restart_proxy":"프록시를 다시 시작하시겠습니까? 모든 것이 ~10초 안에 재구성됩니다.", + "coolify_proxy_restarting":"Coolify 프록시 다시 시작 중...", + "restarting_please_wait":"다시 시작 중입니다... 잠시만 기다려 주십시오...", + "force_restart_proxy":"강제 재시작 프록시", + "use_coolify_proxy":"Coolify 프록시를 사용하시겠습니까?", + "no_destination_found":"목적지를 찾을 수 없습니다", + "new_error_network_already_exists":"다른 팀에 대해 네트워크 {{network}}이(가) 이미 구성되었습니다!", + "new":{ + "saving_and_configuring_proxy":"절약...", + "install_proxy":"그러면 수동 구성 없이 애플리케이션과 서비스에 액세스할 수 있도록 대상에 프록시가 설치됩니다(Docker에 권장됨).

데이터베이스에는 자체 프록시가 있습니다.", + "add_new_destination":"새 목적지 추가", + "predefined_destinations":"사전 정의된 목적지" + } + }, + "sources":{ + "local_docker":"로컬 도커", + "remote_docker":"원격 도커", + "organization_explainer":"조직을 Git 소스로 사용하려면 입력하십시오. 그렇지 않으면 사용자가 사용됩니다." + }, + "source":{ + "new":{ + "git_source":"새 Git 소스 추가", + "official_providers":"공식 제공업체" + }, + "no_git_sources_found":"git 소스를 찾을 수 없습니다.", + "delete_git_source":"삭제", + "permission_denied":"Git 소스를 삭제할 권한이 없습니다.", + "create_new_app":"새 {{name}} 앱 만들기", + "change_app_settings":"{{name}} 앱 설정 변경", + "install_repositories":"저장소 설치", + "application_id":"애플리케이션 ID", + "group_name":"그룹 이름", + "oauth_id":"인증 ID", + "oauth_id_explainer":"OAuth ID는 GitLab 애플리케이션의 고유 식별자입니다.
GitLab OAuth 애플리케이션의 URL에서 찾을 수 있습니다.", + "register_oauth_gitlab":"GitLab에 새 OAuth 애플리케이션 등록", + "gitlab":{ + "self_hosted":"인스턴스 전체 애플리케이션(자체 호스팅)", + "user_owned":"사용자 소유 애플리케이션", + "group_owned":"그룹 소유 애플리케이션", + "gitlab_application_type":"GitLab 애플리케이션 유형", + "already_configured":"GitLab 앱이 이미 구성되어 있습니다." + }, + "github":{ + "redirecting":"Github으로 리디렉션 중..." + } + }, + "services":{ + "all_email_verified":"모든 이메일이 확인되었습니다. 지금 로그인할 수 있습니다.", + "generate_www_non_www_ssl":"www 및 non-www 모두에 대한 인증서를 생성합니다.
미리 두 DNS 항목을 설정해야 합니다.

서비스를 다시 시작해야 합니다." + }, + "service":{ + "stop_service":"중지", + "permission_denied_stop_service":"서비스를 중지할 권한이 없습니다.", + "start_service":"시작", + "permission_denied_start_service":"서비스를 시작할 권한이 없습니다.", + "delete_service":"삭제", + "permission_denied_delete_service":"서비스를 삭제할 권한이 없습니다.", + "no_service":"서비스를 찾을 수 없습니다.", + "logs":"로그" + }, + "setting":{ + "change_language":"언어 변경", + "permission_denied":"이 작업을 수행할 권한이 없습니다. \\n관리자에게 권한 수정을 요청하세요.", + "domain_removed":"도메인이 삭제됨", + "ssl_explainer":"https를 지정하면 Coolify는 https를 통해서만 액세스할 수 있습니다. SSL 인증서가 자동으로 생성됩니다.
www를 지정하면 Coolify가 www가 아닌 ​​곳에서 리디렉션(302)되거나 그 반대의 경우도 마찬가지입니다.

경고: 이미 설정된 도메인을 변경하면 웹훅 및 기타 통합이 중단됩니다! 수동으로 업데이트해야 합니다.", + "must_remove_domain_before_changing":"이 설정을 변경하려면 먼저 도메인을 제거해야 합니다.", + "registration_allowed":"등록이 허용됩니까?", + "registration_allowed_explainer":"애플리케이션에 대한 추가 등록을 허용합니다.
최초 등록 후에는 꺼져 있습니다.", + "coolify_proxy_settings":"Coolify 프록시 설정", + "credential_stat_explainer":"통계 페이지에 대한 자격 증명입니다.", + "auto_update_enabled":"자동 업데이트가 활성화되었습니까?", + "auto_update_enabled_explainer":"Coolify에 대한 자동 업데이트를 활성화합니다. 실행 중인 빌드 프로세스가 없는 경우 배후에서 자동으로 수행됩니다.", + "generate_www_non_www_ssl":"www 및 non-www 모두에 대한 인증서를 생성합니다.
미리 두 DNS 항목을 설정해야 합니다.", + "is_dns_check_enabled":"DNS 확인이 활성화되었습니까?", + "is_dns_check_enabled_explainer":"SSL 인증서를 생성하기 전에 DNS 확인을 비활성화할 수 있습니다.

Coolify가 역방향 프록시 또는 터널 뒤에 있을 때 비활성화하는 것이 유용합니다." + }, + "team":{ + "pending_invitations":"대기 중인 초대", + "accept":"수용하다", + "delete":"삭제", + "member":"회원", + "root":"(뿌리)", + "invited_with_permissions":"{{permission}} 권한으로 {{teamName}}에 초대되었습니다.", + "members":"회원", + "root_team_explainer":"루트 팀입니다. 즉, 이 그룹의 구성원은 인스턴스 전체 설정을 관리하고 Coolify의 모든 권한을 가질 수 있습니다(Linux의 루트 사용자와 같은 경우).", + "permission":"허가", + "you":"너", + "promote_to":"{{grade}}(으)로 승격", + "revoke_invitation":"초대 취소", + "pending_invitation":"대기 중인 초대", + "invite_new_member":"새 회원 초대", + "send_invitation":"초대장을 보내다", + "invite_only_register_explainer":"등록된 사용자만 초대할 수 있습니다.", + "admin":"관리자", + "read":"읽다" + } +} \ No newline at end of file diff --git a/apps/ui/src/lib/locales/pt.json b/apps/ui/src/lib/locales/pt.json new file mode 100644 index 000000000..0ac5deb46 --- /dev/null +++ b/apps/ui/src/lib/locales/pt.json @@ -0,0 +1,341 @@ +{ + "layout":{ + "update_done":"Atualização completa.", + "wait_new_version_startup":"Aguardando a nova versão iniciar...", + "new_version":"Nova versão acessível. Recarregando...", + "switch_to_a_different_team":"Mudar para uma equipa diferente...", + "update_available":"Atualização disponível" + }, + "error":{ + "you_can_find_your_way_back":"Você pode encontrar o seu caminho de volta", + "here":"aqui", + "you_are_lost":"Ooops você está perdido! Mas não tenha medo!" + }, + "index":{ + "dashboard":"Painel", + "applications":"Formulários", + "destinations":"Destinos", + "git_sources":"Fontes Git", + "databases":"Bancos de dados", + "services":"Serviços", + "teams":"Equipes", + "not_implemented_yet":"Ainda não implementado", + "database":"Base de dados", + "settings":"Definições", + "global_settings":"Configurações globais", + "secret":"Segredo", + "team":"Equipe", + "logout":"Sair" + }, + "login":{ + "already_logged_in":"Já logado...", + "authenticating":"Autenticando...", + "login":"Conecte-se" + }, + "forms":{ + "password":"Senha", + "email":"Endereço de email", + "passwords_not_match":"As senhas não coincidem.", + "password_again":"Senha novamente", + "save":"Salvar", + "saving":"Salvando...", + "name":"Nome", + "value":"Valor", + "action":"Ações", + "is_required":"É necessário.", + "add":"Adicionar", + "set":"Definir", + "remove":"Remover", + "path":"Caminho", + "confirm_continue":"Tem certeza de continuar?", + "must_be_stopped_to_modify":"Deve ser parado para modificar.", + "port":"Porta", + "default":"predefinição", + "base_directory":"Diretório base", + "publish_directory":"Publicar diretório", + "generated_automatically_after_start":"Gerado automaticamente após o início", + "roots_password":"Senha do Root", + "root_user":"Usuário raiz", + "eg":"por exemplo", + "user":"Do utilizador", + "loading":"Carregando...", + "version":"Versão", + "host":"Hospedeiro", + "already_used_for":"{{type}} já usado para", + "configuration":"Configuração", + "engine":"Motor", + "network":"Rede", + "ip_address":"Endereço de IP", + "ssh_private_key":"Chave privada SSH", + "type":"Modelo", + "html_url":"URL HTML", + "api_url":"URL da API", + "organization":"Organização", + "new_password":"Nova Senha", + "super_secure_new_password":"Nova senha super segura", + "submit":"Enviar", + "default_email_address":"Endereço de e-mail padrão", + "default_password":"Senha padrão", + "username":"Nome de usuário", + "root_db_user":"Usuário raiz do banco de dados", + "root_db_password":"Senha do banco de dados raiz", + "api_port":"Porta API", + "verifying":"Verificando", + "verify_emails_without_smtp":"Verifique e-mails sem SMTP", + "extra_config":"Configuração extra", + "select_a_service":"Selecione um serviço", + "select_a_service_version":"Selecione uma versão do serviço", + "removing":"Removendo...", + "remove_domain":"Remover domínio", + "public_port_range":"Intervalo de portas públicas", + "public_port_range_explainer":"Portas usadas para expor bancos de dados/serviços/serviços internos.
Adicione-os ao seu firewall (se aplicável).

Você pode especificar um intervalo de portas, por exemplo: 9000-9100", + "no_actions_available":"Nenhuma ação disponível", + "admin_api_key":"Chave de API de administrador" + }, + "register":{ + "register":"Registro", + "registering":"Registrando...", + "first_user":"Você está registrando o primeiro usuário. Será o administrador da sua instância Coolify." + }, + "reset":{ + "reset_password":"Redefinir", + "invalid_secret_key":"Chave secreta inválida.", + "secret_key":"Chave secreta", + "find_path_secret_key":"Você pode encontrá-lo em ~/coolify/.env (COOLIFY_SECRET_KEY)" + }, + "application":{ + "configuration":{ + "buildpack":{ + "choose_this_one":"Escolha este..." + }, + "branch_already_in_use":"Esta ramificação já é usada por outro aplicativo. Os webhooks não funcionarão neste caso para ambos os aplicativos. Tem certeza de que deseja usá-lo?", + "no_repositories_configured":"Nenhum repositório configurado para seu aplicativo Git.", + "configure_it_now":"Configure agora", + "loading_repositories":"Carregando repositórios...", + "select_a_repository":"Selecione um repositório", + "loading_branches":"Carregando ramos...", + "select_a_repository_first":"Selecione um repositório primeiro", + "select_a_branch":"Selecione uma filial", + "loading_groups":"Carregando grupos...", + "select_a_group":"Selecione um grupo", + "loading_projects":"Carregando projetos...", + "select_a_project":"Por favor selecione um projeto", + "no_projects_found":"Nenhum projeto encontrado", + "no_branches_found":"Nenhuma ramificação encontrada", + "configure_build_pack":"Configurar pacote de compilação", + "scanning_repository_suggest_build_pack":"Verificando repositório para sugerir um pacote de compilação para você...", + "found_lock_file":"Arquivo de bloqueio encontrado para {{packageManager}}.
Usando-o para comandos de comandos predefinidos.", + "configure_destination":"Configurar destino", + "no_configurable_destination":"Nenhum destino configurável encontrado", + "select_a_repository_project":"Selecione um Repositório/Projeto", + "select_a_git_source":"Selecione uma fonte Git", + "no_configurable_git":"Nenhuma fonte Git configurável encontrada", + "configuration_missing":"Configuração ausente" + }, + "build":{ + "queued_waiting_exec":"Na fila e aguardando execução.", + "build_logs_of":"Construir registros de", + "running":"Corrida", + "queued":"Enfileiradas", + "finished_in":"Terminando em", + "load_more":"Carregue mais", + "no_logs":"Nenhum registro encontrado", + "waiting_logs":"Aguardando os logs..." + }, + "preview":{ + "need_during_buildtime":"Precisa durante o tempo de construção?", + "setup_secret_app_first":"Você pode adicionar segredos a implantações de PR/MR. Por favor, adicione segredos ao aplicativo primeiro.
Útil para criar ambientes de preparação.", + "values_overwriting_app_secrets":"Esses valores substituem os segredos do aplicativo em implantações PR/MR. Útil para criar ambientes de preparação.", + "redeploy":"Reimplantar", + "no_previews_available":"Nenhuma visualização disponível" + }, + "secrets":{ + "secret_saved":"Segredo salvo.", + "use_isbuildsecret":"Use isBuildSecret", + "secrets_for":"Segredos para" + }, + "storage":{ + "path_is_required":"O caminho é obrigatório.", + "storage_saved":"Armazenamento salvo.", + "storage_updated":"Armazenamento atualizado.", + "storage_deleted":"Armazenamento excluído.", + "persistent_storage_explainer":"Você pode especificar qualquer pasta que deseja que seja persistente nas implantações.
/example significa que ela preservará /app/ example no contêiner, pois /app é o diretório raiz para seu aplicativo.

Isto é útil para armazenar dados como um banco de dados (SQLite) ou um cache." + }, + "deployment_queued":"Implantação em fila.", + "confirm_to_delete":"Tem certeza de que deseja excluir '{{name}}'?", + "stop_application":"Parar aplicativo", + "permission_denied_stop_application":"Você não tem permissão para parar o aplicativo.", + "rebuild_application":"Reconstruir aplicativo", + "permission_denied_rebuild_application":"Você não tem permissão para reconstruir o aplicativo.", + "build_and_start_application":"Implantar", + "permission_denied_build_and_start_application":"Você não tem permissão para implantar o aplicativo.", + "configurations":"Configurações", + "secret":"Segredos", + "persistent_storage":"Armazenamento persistente", + "previews":"Visualizações", + "logs":"Registros de aplicativos", + "build_logs":"Construir registros", + "delete_application":"Excluir", + "permission_denied_delete_application":"Você não tem permissão para excluir este aplicativo", + "domain_already_in_use":"O domínio {{domain}} já está em uso.", + "dns_not_set_error":"DNS não definido corretamente ou propagado para {{domain}}.

Verifique suas configurações de DNS.", + "domain_required":"O domínio é obrigatório.", + "settings_saved":"Configuração salva.", + "dns_not_set_partial_error":"DNS não definido", + "domain_not_valid":"Não foi possível resolver o domínio ou não está apontando para o endereço IP do servidor.

Verifique sua configuração de DNS e tente novamente.", + "git_source":"Fonte do Git", + "git_repository":"Repositório Git", + "build_pack":"Pacote de compilação", + "base_image":"Imagem de implantação", + "base_image_explainer":"Imagem que será usada para a implantação.", + "base_build_image":"Construir imagem", + "base_build_image_explainer":"Imagem que será usada durante o processo de compilação.", + "destination":"Destino", + "application":"Inscrição", + "url_fqdn":"URL (FQDN)", + "domain_fqdn":"Domínio (FQDN)", + "https_explainer":"Se você especificar https, o aplicativo será acessível apenas por https. O certificado SSL será gerado para você.
Se você especificar www, o aplicativo será redirecionado (302) de não www e vice-versa.
< br>Para modificar o domínio, você deve primeiro parar o aplicativo.

Você deve configurar seu DNS para apontar para o IP do servidor com antecedência.", + "ssl_www_and_non_www":"Gerar SSL para www e não www?", + "ssl_explainer":"Ele irá gerar certificados para www e não www.
Você precisa ter ambas as entradas DNS definidas com antecedência.

Útil se você espera receber visitantes em ambas.", + "install_command":"Comando de instalação", + "build_command":"Comando de compilação", + "start_command":"Comando Iniciar", + "directory_to_use_explainer":"Diretório a ser usado como base para todos os comandos.
Pode ser útil com monorepos.", + "publish_directory_explainer":"Diretório contendo todos os ativos para implantação.
Por exemplo: dist,_site ou public< /span>.", + "features":"Características", + "enable_automatic_deployment":"Ativar implantação automática", + "enable_auto_deploy_webhooks":"Habilite a implantação automática por meio de webhooks.", + "enable_mr_pr_previews":"Ativar visualizações de MR/PR", + "expose_a_port":"Expor uma porta", + "enable_preview_deploy_mr_pr_requests":"Habilite implantações de visualização de solicitações de pull ou mesclagem.", + "debug_logs":"Registros de depuração", + "enable_debug_log_during_build":"Ative os registros de depuração durante a fase de compilação.
Informações confidenciais podem ser visíveis e salvas nos registros.", + "cant_activate_auto_deploy_without_repo":"Não é possível ativar implantações automáticas até que apenas um aplicativo seja definido para este repositório/ramificação.", + "no_applications_found":"Nenhum aplicativo encontrado", + "secret__batch_dot_env":"Colar arquivo .env", + "batch_secrets":"Adicionar segredos em lote" + }, + "general":"Em geral", + "database":{ + "default_database":"Banco de dados padrão", + "generated_automatically_after_set_to_public":"Gerado automaticamente após definido como público", + "connection_string":"Cadeia de conexão", + "set_public":"Defina-o como público", + "warning_database_public":"Seu banco de dados estará acessível pela internet.
Leve a segurança a sério neste caso!", + "change_append_only_mode":"Alterar o modo somente anexar", + "warning_append_only":"Útil se você deseja restaurar dados redis de um backup.
É necessário reiniciar o banco de dados.", + "select_database_type":"Selecione um tipo de banco de dados", + "select_database_version":"Selecione uma versão do banco de dados", + "confirm_stop":"Tem certeza de que deseja parar {{name}}?", + "stop_database":"Pare", + "permission_denied_stop_database":"Você não tem permissão para parar o banco de dados.", + "start_database":"Começar", + "permission_denied_start_database":"Você não tem permissão para iniciar o banco de dados.", + "delete_database":"Excluir", + "permission_denied_delete_database":"Você não tem permissão para excluir um banco de dados", + "no_databases_found":"Nenhum banco de dados encontrado", + "logs":"Histórico" + }, + "destination":{ + "delete_destination":"Excluir", + "permission_denied_delete_destination":"Você não tem permissão para excluir este destino", + "add_to_coolify":"Adicionar ao Coolify", + "coolify_proxy_stopped":"Coolify Proxy parou!", + "coolify_proxy_started":"Coolify Proxy iniciado!", + "confirm_restart_proxy":"Tem certeza de que deseja reiniciar o proxy? Tudo será reconfigurado em ~10 segundos.", + "coolify_proxy_restarting":"Coolify Proxy reiniciando...", + "restarting_please_wait":"Reiniciando... aguarde...", + "force_restart_proxy":"Forçar reinicialização do proxy", + "use_coolify_proxy":"Usar Coolify Proxy?", + "no_destination_found":"Nenhum destino encontrado", + "new_error_network_already_exists":"Rede {{network}} já configurada para outra equipe!", + "new":{ + "saving_and_configuring_proxy":"Salvando...", + "install_proxy":"Isso instalará um proxy no destino para permitir que você acesse seus aplicativos e serviços sem qualquer configuração manual (recomendado para o Docker).

Os bancos de dados terão seu próprio proxy.", + "add_new_destination":"Adicionar novo destino", + "predefined_destinations":"Destinos predefinidos" + } + }, + "sources":{ + "local_docker":"Docker local", + "remote_docker":"Docker remoto", + "organization_explainer":"Preencha-o se quiser usar o de uma organização como seu Git Source. Caso contrário, seu usuário será usado." + }, + "source":{ + "new":{ + "git_source":"Adicionar nova fonte Git", + "official_providers":"Fornecedores oficiais" + }, + "no_git_sources_found":"Nenhuma fonte git encontrada", + "delete_git_source":"Excluir", + "permission_denied":"Você não tem permissão para excluir uma fonte Git", + "create_new_app":"Criar novo aplicativo {{name}}", + "change_app_settings":"Alterar {{name}} configurações do aplicativo", + "install_repositories":"Instalar repositórios", + "application_id":"ID do aplicativo", + "group_name":"Nome do grupo", + "oauth_id":"ID OAuth", + "oauth_id_explainer":"O OAuth ID é o identificador exclusivo do aplicativo GitLab.
Você pode encontrá-lo no URL do seu aplicativo GitLab OAuth.", + "register_oauth_gitlab":"Registre um novo aplicativo OAuth no GitLab", + "gitlab":{ + "self_hosted":"Aplicativo em toda a instância (auto-hospedado)", + "user_owned":"Aplicativo de propriedade do usuário", + "group_owned":"Aplicativo de propriedade do grupo", + "gitlab_application_type":"Tipo de aplicativo GitLab", + "already_configured":"O aplicativo GitLab já está configurado." + }, + "github":{ + "redirecting":"Redirecionando para o Github..." + } + }, + "services":{ + "all_email_verified":"Todos os e-mails são verificados. Você pode entrar agora.", + "generate_www_non_www_ssl":"Ele irá gerar certificados para www e não www.
Você precisa ter ambas as entradas DNS definidas com antecedência.

O serviço precisa ser reiniciado." + }, + "service":{ + "stop_service":"Pare", + "permission_denied_stop_service":"Você não tem permissão para interromper o serviço.", + "start_service":"Começar", + "permission_denied_start_service":"Você não tem permissão para iniciar o serviço.", + "delete_service":"Excluir", + "permission_denied_delete_service":"Você não tem permissão para excluir um serviço.", + "no_service":"Nenhum serviço encontrado", + "logs":"Histórico" + }, + "setting":{ + "change_language":"Mudar idioma", + "permission_denied":"Você não tem permissão para fazer isso. \\nPeça a um administrador para modificar suas permissões.", + "domain_removed":"Domínio removido", + "ssl_explainer":"Se você especificar https, o Coolify será acessível apenas por https. O certificado SSL será gerado para você.
Se você especificar www, Coolify será redirecionado (302) de não www e vice-versa.

AVISO: Se você alterar um domínio já definido, isso interromperá webhooks e outras integrações! Você precisa atualizá-los manualmente.", + "must_remove_domain_before_changing":"Deve remover o domínio antes de alterar esta configuração.", + "registration_allowed":"Registro permitido?", + "registration_allowed_explainer":"Permitir mais registros no aplicativo.
É desligado após o primeiro registro.", + "coolify_proxy_settings":"Configurações de proxy do Coolify", + "credential_stat_explainer":"Credenciais para a página de estatísticas.", + "auto_update_enabled":"Atualização automática habilitada?", + "auto_update_enabled_explainer":"Habilite atualizações automáticas para Coolify. Isso será feito automaticamente nos bastidores, se não houver nenhum processo de compilação em execução.", + "generate_www_non_www_ssl":"Ele irá gerar certificados para www e não www.
Você precisa ter ambas as entradas de DNS configuradas antecipadamente.", + "is_dns_check_enabled":"Verificação de DNS habilitada?", + "is_dns_check_enabled_explainer":"Você pode desabilitar a verificação de DNS antes de criar certificados SSL.

Desligá-la é útil quando o Coolify está atrás de um proxy reverso ou túnel." + }, + "team":{ + "pending_invitations":"Convites pendentes", + "accept":"Aceitar", + "delete":"Excluir", + "member":"membros)", + "root":"(raiz)", + "invited_with_permissions":"Convidado para {{teamName}} com permissão {{permission}}.", + "members":"Membros", + "root_team_explainer":"Esta é a equipe raiz. Isso significa que os membros deste grupo podem gerenciar as configurações de toda a instância e ter todos os privilégios no Coolify (imagine como usuário root no Linux).", + "permission":"Permissão", + "you":"Você", + "promote_to":"Promover para {{grade}}", + "revoke_invitation":"Revogar convite", + "pending_invitation":"Convite pendente", + "invite_new_member":"Convidar novo membro", + "send_invitation":"Enviar convite", + "invite_only_register_explainer":"Você só pode convidar usuários registrados.", + "admin":"Administrador", + "read":"Ler" + } +} \ No newline at end of file diff --git a/apps/ui/src/lib/translations.ts b/apps/ui/src/lib/translations.ts index 3ead4e1ec..9cc71a118 100644 --- a/apps/ui/src/lib/translations.ts +++ b/apps/ui/src/lib/translations.ts @@ -1,11 +1,18 @@ import i18n from 'sveltekit-i18n'; +import { derived, writable } from "svelte/store"; import lang from './lang.json'; +export let currentLocale = writable("en"); +export let debugTranslation = writable(false); + /** @type {import('sveltekit-i18n').Config} */ export const config = { fallbackLocale: 'en', translations: { en: { lang }, + es: { lang }, + pt: { lang }, + ko: { lang }, fr: { lang } }, loaders: [ @@ -14,12 +21,27 @@ export const config = { key: '', loader: async () => (await import('./locales/en.json')).default }, + { + locale: 'es', + key: '', + loader: async () => (await import('./locales/es.json')).default + }, + { + locale: 'pt', + key: '', + loader: async () => (await import('./locales/pt.json')).default + }, { locale: 'fr', key: '', loader: async () => (await import('./locales/fr.json')).default + }, + { + locale: 'ko', + key: '', + loader: async () => (await import('./locales/ko.json')).default } ] }; -export const { t, locales, locale, loadTranslations } = new i18n(config); +export const { t, locales, locale, loadTranslations } = new i18n(config); \ No newline at end of file diff --git a/apps/ui/src/routes/__layout.svelte b/apps/ui/src/routes/__layout.svelte index 4663e6d9f..7c2bcf36d 100644 --- a/apps/ui/src/routes/__layout.svelte +++ b/apps/ui/src/routes/__layout.svelte @@ -95,6 +95,7 @@ import Toasts from '$lib/components/Toasts.svelte'; import Tooltip from '$lib/components/Tooltip.svelte'; import { onMount } from 'svelte'; + import LocalePicker from '$lib/components/LocalePicker.svelte'; if (userId) $appSession.userId = userId; if (teamId) $appSession.teamId = teamId; @@ -292,6 +293,9 @@
+
+ +
@@ -311,19 +315,22 @@ {/if} {/if}