mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd5d437979 | ||
|
|
453cd7aed0 | ||
|
|
3e5dc86b4f | ||
|
|
7c7af6e4e9 | ||
|
|
f7d76d9799 | ||
|
|
5f30d94ea9 | ||
|
|
c99f3f97f4 | ||
|
|
653a6e27f6 | ||
|
|
fde617a7ac | ||
|
|
2e7226504b | ||
|
|
47241ba296 | ||
|
|
daf5b1dc33 | ||
|
|
ab17a63b44 | ||
|
|
6cb55f89b6 | ||
|
|
135d7a86b6 | ||
|
|
2d59be18c7 | ||
|
|
90ac87f217 | ||
|
|
6d91c95eeb | ||
|
|
4a29ea08e2 | ||
|
|
b755eee77c | ||
|
|
96c041f9ec | ||
|
|
b79bdc56a1 | ||
|
|
2337da5d6c | ||
|
|
2b0f1d78a2 | ||
|
|
73b29e9005 | ||
|
|
5807523488 | ||
|
|
8fcab11610 | ||
|
|
d7ebc84a23 | ||
|
|
65cee92ed2 | ||
|
|
2943ed6b37 | ||
|
|
775fd688ff | ||
|
|
42302e5623 | ||
|
|
ba2dfc20c7 | ||
|
|
3fc15588c4 | ||
|
|
4ed7ff5e84 | ||
|
|
dc5ee94e33 | ||
|
|
b57a966936 | ||
|
|
51cb0e3b27 | ||
|
|
ce3c5a0675 | ||
|
|
785b1d3f68 | ||
|
|
123873a41c | ||
|
|
d5da4a9ed8 | ||
|
|
73d0da9d59 | ||
|
|
0daf13f5a2 | ||
|
|
39442bb2a0 | ||
|
|
ca87c9732d | ||
|
|
9de3066c17 | ||
|
|
faef5af96c | ||
|
|
4766542b3a | ||
|
|
1529c649ff | ||
|
|
3d5d45d676 | ||
|
|
b037c3953e | ||
|
|
c5e7b8792a | ||
|
|
2755645898 |
@@ -1,31 +0,0 @@
|
||||
# PR Workflow for Appwrite
|
||||
|
||||
## Branch Targeting
|
||||
|
||||
**Important:** Appwrite does NOT use `main` as the primary development branch.
|
||||
|
||||
PRs should target the **current version branch** (e.g., `1.8.x`, `1.9.x`), not `main`.
|
||||
|
||||
### How to determine the correct target branch
|
||||
|
||||
1. Check which version branch you're currently on: `git branch --show-current`
|
||||
2. Look for branches matching the pattern `X.Y.x` (e.g., `1.8.x`, `1.9.x`)
|
||||
3. The current active development branch is typically the highest version number with the `.x` suffix
|
||||
|
||||
### When creating PRs
|
||||
|
||||
Always use the version branch as the base:
|
||||
|
||||
```bash
|
||||
# Correct - targets the version branch
|
||||
gh pr create --base 1.8.x --title "Your PR title" --body "..."
|
||||
|
||||
# Wrong - do not target main
|
||||
gh pr create --base main ...
|
||||
```
|
||||
|
||||
### Branch naming convention
|
||||
|
||||
- `X.Y.x` branches (e.g., `1.8.x`) - Active development branches for each minor version
|
||||
- `main` - Not used for regular PRs; reserved for release management
|
||||
- Feature branches should be created from and merged back into the current version branch
|
||||
@@ -1,17 +0,0 @@
|
||||
reviews:
|
||||
path_filters:
|
||||
- "!app/config/specs/**"
|
||||
- "!docs/examples/**"
|
||||
- "!docs/references/**"
|
||||
- "!docs/sdks/**"
|
||||
auto_review:
|
||||
base_branches:
|
||||
- main
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
high_level_summary: false
|
||||
poem: false
|
||||
sequence_diagrams: false
|
||||
collapse_walkthrough: true
|
||||
changed_files_summary: false
|
||||
@@ -1,48 +1,24 @@
|
||||
_APP_ENV=development
|
||||
_APP_EDITION=self-hosted
|
||||
_APP_LOCALE=en
|
||||
_APP_WORKER_PER_CORE=6
|
||||
_APP_COMPRESSION_ENABLED=enabled
|
||||
_APP_COMPRESSION_MIN_SIZE_BYTES=1024
|
||||
_APP_CONSOLE_WHITELIST_ROOT=disabled
|
||||
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||
_APP_CONSOLE_SESSION_ALERTS=enabled
|
||||
_APP_CONSOLE_WHITELIST_IPS=
|
||||
_APP_CONSOLE_COUNTRIES_DENYLIST=AQ
|
||||
_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io
|
||||
_APP_CONSOLE_SCHEMA=appwriteio
|
||||
_APP_MIGRATION_HOST=appwrite
|
||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||
_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io
|
||||
_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
|
||||
_APP_EMAIL_SECURITY=security@appwrite.io
|
||||
_APP_EMAIL_CERTIFICATES=certificates@appwrite.io
|
||||
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io
|
||||
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||
_APP_CUSTOM_DOMAIN_DENY_LIST=
|
||||
_APP_OPTIONS_ABUSE=disabled
|
||||
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||
_APP_DNS=172.16.238.100 # CoreDNS
|
||||
_APP_DOMAIN=appwrite.test
|
||||
_APP_CONSOLE_DOMAIN=localhost
|
||||
_APP_CONSOLE_TRUSTED_PROJECTS=trusted-project,another-trusted-project
|
||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost,rebranded.localhost
|
||||
_APP_DOMAIN_TARGET_CNAME=cname.localhost
|
||||
_APP_DOMAIN_TARGET_A=203.0.0.1
|
||||
_APP_DOMAIN_TARGET_AAAA=::1
|
||||
_APP_DOMAIN_TARGET_CAA=digicert.com
|
||||
_APP_RULES_FORMAT=md5
|
||||
_APP_DOMAIN=demo.appwrite.io
|
||||
_APP_DOMAIN_TARGET=demo.appwrite.io
|
||||
_APP_REDIS_HOST=redis
|
||||
_APP_REDIS_PORT=6379
|
||||
_APP_REDIS_PASS=
|
||||
_APP_REDIS_USER=
|
||||
COMPOSE_PROFILES=mongodb
|
||||
_APP_DB_ADAPTER=mongodb
|
||||
_APP_DB_HOST=mongodb
|
||||
_APP_DB_PORT=27017
|
||||
_APP_DB_HOST=mariadb
|
||||
_APP_DB_PORT=3306
|
||||
_APP_DB_SCHEMA=appwrite
|
||||
_APP_DB_USER=user
|
||||
_APP_DB_PASS=password
|
||||
@@ -52,7 +28,6 @@ _APP_STORAGE_S3_ACCESS_KEY=
|
||||
_APP_STORAGE_S3_SECRET=
|
||||
_APP_STORAGE_S3_REGION=us-east-1
|
||||
_APP_STORAGE_S3_BUCKET=
|
||||
_APP_STORAGE_S3_ENDPOINT=
|
||||
_APP_STORAGE_DO_SPACES_ACCESS_KEY=
|
||||
_APP_STORAGE_DO_SPACES_SECRET=
|
||||
_APP_STORAGE_DO_SPACES_REGION=us-east-1
|
||||
@@ -72,68 +47,44 @@ _APP_STORAGE_WASABI_BUCKET=
|
||||
_APP_STORAGE_ANTIVIRUS=disabled
|
||||
_APP_STORAGE_ANTIVIRUS_HOST=clamav
|
||||
_APP_STORAGE_ANTIVIRUS_PORT=3310
|
||||
_APP_INFLUXDB_HOST=influxdb
|
||||
_APP_INFLUXDB_PORT=8086
|
||||
_APP_STATSD_HOST=telegraf
|
||||
_APP_STATSD_PORT=8125
|
||||
_APP_SMTP_HOST=maildev
|
||||
_APP_SMTP_PORT=1025
|
||||
_APP_SMTP_SECURE=
|
||||
_APP_SMTP_USERNAME=user
|
||||
_APP_SMTP_PASSWORD=password
|
||||
_APP_SMTP_USERNAME=
|
||||
_APP_SMTP_PASSWORD=
|
||||
_APP_SMS_PROVIDER=sms://username:password@mock
|
||||
_APP_SMS_FROM=+123456789
|
||||
_APP_SMS_PROJECTS_DENY_LIST=
|
||||
_APP_STORAGE_LIMIT=30000000
|
||||
_APP_STORAGE_PREVIEW_LIMIT=20000000
|
||||
_APP_COMPUTE_SIZE_LIMIT=30000000
|
||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
||||
_APP_FUNCTIONS_TIMEOUT=900
|
||||
_APP_SITES_TIMEOUT=30
|
||||
_APP_COMPUTE_BUILD_TIMEOUT=900
|
||||
_APP_COMPUTE_CPUS=8
|
||||
_APP_COMPUTE_MEMORY=8192
|
||||
_APP_COMPUTE_INACTIVE_THRESHOLD=600
|
||||
_APP_COMPUTE_MAINTENANCE_INTERVAL=600
|
||||
_APP_COMPUTE_RUNTIMES_NETWORK=runtimes
|
||||
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
||||
_APP_FUNCTIONS_CONTAINERS=10
|
||||
_APP_FUNCTIONS_CPUS=0
|
||||
_APP_FUNCTIONS_MEMORY=0
|
||||
_APP_FUNCTIONS_MEMORY_SWAP=0
|
||||
_APP_FUNCTIONS_INACTIVE_THRESHOLD=60
|
||||
OPEN_RUNTIMES_NETWORK=appwrite_runtimes
|
||||
_APP_EXECUTOR_SECRET=your-secret-key
|
||||
_APP_EXECUTOR_HOST=http://exc1/v1
|
||||
_APP_BROWSER_HOST=http://appwrite-browser:3000/v1
|
||||
_APP_FUNCTIONS_RUNTIMES=node-22
|
||||
_APP_SITES_RUNTIMES=static-1,node-22
|
||||
_APP_FUNCTIONS_PROXY_SECRET=your-secret-key
|
||||
_APP_FUNCTIONS_PROXY_HOST=http://appwrite-functions-proxy/v1
|
||||
_APP_MAINTENANCE_INTERVAL=86400
|
||||
_APP_MAINTENANCE_START_TIME=12:00
|
||||
_APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
||||
_APP_MAINTENANCE_RETENTION_ABUSE=86400
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800
|
||||
_APP_USAGE_AGGREGATION_INTERVAL=30
|
||||
_APP_STATS_RESOURCES_INTERVAL=30
|
||||
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
||||
_APP_INTERVAL_DOMAIN_VERIFICATION=120
|
||||
_APP_INTERVAL_CLEANUP_STALE_EXECUTIONS=300
|
||||
_APP_USAGE_TIMESERIES_INTERVAL=2
|
||||
_APP_USAGE_DATABASE_INTERVAL=15
|
||||
_APP_USAGE_STATS=enabled
|
||||
_APP_LOGGING_PROVIDER=
|
||||
_APP_LOGGING_CONFIG=
|
||||
_APP_LOGGING_CONFIG_REALTIME=
|
||||
_APP_GRAPHQL_INTROSPECTION=enabled
|
||||
_APP_GRAPHQL_MAX_BATCH_SIZE=10
|
||||
_APP_GRAPHQL_MAX_COMPLEXITY=250
|
||||
_APP_GRAPHQL_MAX_DEPTH=4
|
||||
_APP_DOCKER_HUB_USERNAME=
|
||||
_APP_DOCKER_HUB_PASSWORD=
|
||||
_APP_VCS_GITHUB_APP_NAME=
|
||||
_APP_VCS_GITHUB_PRIVATE_KEY=disabled
|
||||
_APP_VCS_GITHUB_APP_ID=
|
||||
_APP_VCS_GITHUB_CLIENT_ID=
|
||||
_APP_VCS_GITHUB_CLIENT_SECRET=
|
||||
_APP_VCS_GITHUB_WEBHOOK_SECRET=
|
||||
_APP_MIGRATIONS_FIREBASE_CLIENT_ID=
|
||||
_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=
|
||||
_APP_ASSISTANT_OPENAI_API_KEY=
|
||||
_APP_MESSAGE_SMS_TEST_DSN=
|
||||
_APP_MESSAGE_EMAIL_TEST_DSN=
|
||||
_APP_MESSAGE_PUSH_TEST_DSN=
|
||||
_APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10
|
||||
_APP_PROJECT_REGIONS=default
|
||||
_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000
|
||||
_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main
|
||||
_APP_TRUSTED_HEADERS=x-forwarded-for
|
||||
_APP_POOL_ADAPTER=stack
|
||||
_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite
|
||||
DOCKERHUB_PULL_USERNAME=
|
||||
DOCKERHUB_PULL_PASSWORD=
|
||||
DOCKERHUB_PULL_EMAIL=
|
||||
_APP_FUNCTIONS_PROXY_ADAPTER=round-robin
|
||||
_APP_EXECUTORS=exc1,exc2
|
||||
# _APP_EXECUTORS=exc1
|
||||
+28
-9
@@ -1,9 +1,28 @@
|
||||
app/config/** linguist-detectable=false
|
||||
app/views/** linguist-detectable=false
|
||||
app/controllers/** linguist-detectable=false
|
||||
src/** linguist-detectable=false
|
||||
tests/** linguist-detectable=false
|
||||
public/scripts/** linguist-detectable=false
|
||||
public/dist/scripts/** linguist-detectable=false
|
||||
|
||||
.github/workflows/*.lock.yml linguist-generated=true merge=ours
|
||||
app/config/* linguist-detectable=false
|
||||
app/config/*/* linguist-detectable=false
|
||||
app/config/*/*/* linguist-detectable=false
|
||||
app/config/*/*/*/* linguist-detectable=false
|
||||
app/views/* linguist-detectable=false
|
||||
app/views/*/* linguist-detectable=false
|
||||
app/views/*/*/* linguist-detectable=false
|
||||
app/views/*/*/*/* linguist-detectable=false
|
||||
app/controllers/* linguist-detectable=false
|
||||
app/controllers/*/* linguist-detectable=false
|
||||
app/controllers/*/*/* linguist-detectable=false
|
||||
app/controllers/*/*/*/* linguist-detectable=false
|
||||
app/controllers/*/*/*/*/* linguist-detectable=false
|
||||
src/* linguist-detectable=false
|
||||
src/*/* linguist-detectable=false
|
||||
src/*/*/* linguist-detectable=false
|
||||
src/*/*/*/* linguist-detectable=false
|
||||
src/*/*/*/*/* linguist-detectable=false
|
||||
tests/* linguist-detectable=false
|
||||
tests/*/* linguist-detectable=false
|
||||
tests/*/*/* linguist-detectable=false
|
||||
tests/*/*/*/* linguist-detectable=false
|
||||
tests/*/*/*/*/* linguist-detectable=false
|
||||
tests/*/*/*/*/*/* linguist-detectable=false
|
||||
public/scripts/* linguist-detectable=false
|
||||
public/scripts/*/*/* linguist-detectable=false
|
||||
public/scripts/*/*/*/* linguist-detectable=false
|
||||
public/dist/scripts/* linguist-detectable=false
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
name: "🐛 Bug Report"
|
||||
description: "Submit a bug report to help us improve"
|
||||
title: "🐛 Bug Report: "
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out our bug report form 🙏
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "👟 Reproduction steps"
|
||||
description: "How do you trigger this bug? Please walk us through it step by step."
|
||||
placeholder: "When I ..."
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "👍 Expected behavior"
|
||||
description: "What did you think would happen?"
|
||||
placeholder: "It should ..."
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "👎 Actual Behavior"
|
||||
description: "What did actually happen? Add screenshots, if applicable."
|
||||
placeholder: "It actually ..."
|
||||
- type: dropdown
|
||||
id: appwrite-version
|
||||
attributes:
|
||||
label: "🎲 Appwrite version"
|
||||
description: "What version of Appwrite are you running?"
|
||||
options:
|
||||
- Version 1.0.x
|
||||
- Version 0.15.x
|
||||
- Version 0.14.x
|
||||
- Version 0.13.x
|
||||
- Version 0.12.x
|
||||
- Version 0.11.x
|
||||
- Version 0.10.x
|
||||
- Version 0.9.x
|
||||
- Version 0.8.x
|
||||
- Version 0.7.x
|
||||
- Version 0.6.x
|
||||
- Different version (specify in environment)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: "💻 Operating system"
|
||||
description: "What OS is your server / device running on?"
|
||||
options:
|
||||
- Linux
|
||||
- MacOS
|
||||
- Windows
|
||||
- Something else
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
validations:
|
||||
required: false
|
||||
attributes:
|
||||
label: "🧱 Your Environment"
|
||||
description: "Is your environment customized in any way?"
|
||||
placeholder: "I use Cloudflare for ..."
|
||||
- type: checkboxes
|
||||
id: no-duplicate-issues
|
||||
attributes:
|
||||
label: "👀 Have you spent some time to check if this issue has been raised before?"
|
||||
description: "Have you Googled for a similar issue or checked our older issues for a similar bug?"
|
||||
options:
|
||||
- label: "I checked and didn't find similar issue"
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: read-code-of-conduct
|
||||
attributes:
|
||||
label: "🏢 Have you read the Code of Conduct?"
|
||||
options:
|
||||
- label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)"
|
||||
required: true
|
||||
@@ -0,0 +1,32 @@
|
||||
name: "📚 Documentation"
|
||||
description: "Report an issue related to documentation"
|
||||
title: "📚 Documentation: "
|
||||
labels: [documentation]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to make our documentation better 🙏
|
||||
- type: textarea
|
||||
id: issue-description
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "💭 Description"
|
||||
description: "A clear and concise description of what the issue is."
|
||||
placeholder: "Documentation should not ..."
|
||||
- type: checkboxes
|
||||
id: no-duplicate-issues
|
||||
attributes:
|
||||
label: "👀 Have you spent some time to check if this issue has been raised before?"
|
||||
description: "Have you Googled for a similar issue or checked our older issues for a similar bug?"
|
||||
options:
|
||||
- label: "I checked and didn't find similar issue"
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: read-code-of-conduct
|
||||
attributes:
|
||||
label: "🏢 Have you read the Code of Conduct?"
|
||||
options:
|
||||
- label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)"
|
||||
required: true
|
||||
@@ -0,0 +1,40 @@
|
||||
name: 🚀 Feature
|
||||
description: "Submit a proposal for a new feature"
|
||||
title: "🚀 Feature: "
|
||||
labels: [feature]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out our feature request form 🙏
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "🔖 Feature description"
|
||||
description: "A clear and concise description of what the feature is."
|
||||
placeholder: "You should add ..."
|
||||
- type: textarea
|
||||
id: pitch
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "🎤 Pitch"
|
||||
description: "Please explain why this feature should be implemented and how it would be used. Add examples, if applicable."
|
||||
placeholder: "In my use-case, ..."
|
||||
- type: checkboxes
|
||||
id: no-duplicate-issues
|
||||
attributes:
|
||||
label: "👀 Have you spent some time to check if this issue has been raised before?"
|
||||
description: "Have you Googled for a similar issue or checked our older issues for a similar bug?"
|
||||
options:
|
||||
- label: "I checked and didn't find similar issue"
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: read-code-of-conduct
|
||||
attributes:
|
||||
label: "🏢 Have you read the Code of Conduct?"
|
||||
options:
|
||||
- label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)"
|
||||
required: true
|
||||
@@ -11,17 +11,21 @@ Happy contributing!
|
||||
|
||||
## What does this PR do?
|
||||
|
||||
(Provide a description of what this PR does and why it's needed.)
|
||||
(Provide a description of what this PR does.)
|
||||
|
||||
## Test Plan
|
||||
|
||||
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
|
||||
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
|
||||
|
||||
## Related PRs and Issues
|
||||
|
||||
- (Related PR or issue)
|
||||
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
|
||||
|
||||
## Checklist
|
||||
### Have you added your change to the [Changelog](https://github.com/appwrite/appwrite/blob/master/CHANGES.md)?
|
||||
|
||||
- [ ] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||
- [ ] If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?
|
||||
(The CHANGES.md file tracks all the changes that make it to the `main` branch. Add your change to this file in the following format)
|
||||
- One line description of your PR [#pr_number](Link to your PR)
|
||||
|
||||
### Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
# Fixes and upgrades for the Appwrite Auth / Users / Teams services.
|
||||
"product / auth":
|
||||
- "(auth|session|login|logout|register|2fa|mfa|users|teams|memberships|invite|oauth|oauth2|sso|jwt)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Realtime API.
|
||||
"api / realtime":
|
||||
- "(realtime|subscribe|websockets)"
|
||||
|
||||
# Console, UI and UX issues
|
||||
"product / console":
|
||||
- "(console)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Storage.
|
||||
"product / storage":
|
||||
- "(storage|bucket|file|image|preview|download)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Database.
|
||||
"product / databases":
|
||||
- "(database|collection|tables|attribute|column|document|row|query|queries|indexes|search|filter|sort|pagination)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Functions.
|
||||
"product / functions":
|
||||
- "(function|runtime|deployment|execution|trigger|cron|schedule)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Docs.
|
||||
# "product / docs":
|
||||
# -
|
||||
|
||||
# Fixes and upgrades for the Appwrite Migrations.
|
||||
"product / migrations":
|
||||
- "(migrate|migration)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Messaging.
|
||||
"product / messaging":
|
||||
- "(messaging|email|sms|push|provider|topic|target|notification)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Platform.
|
||||
# "product / platform":
|
||||
# -
|
||||
|
||||
# Fixes and upgrades for database relationships
|
||||
"feature / relationships":
|
||||
- "(relationship)"
|
||||
|
||||
# Issues found only on Appwrite Cloud
|
||||
# "product / cloud":
|
||||
# -
|
||||
|
||||
# Fixes and upgrades for the Appwrite VCS.
|
||||
"product / vcs":
|
||||
- "(repo|push|vcs|repository)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite GraphQL API.
|
||||
"api / graphql":
|
||||
- "(graphql|gql|mutation)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Assistant.
|
||||
"product / assistant":
|
||||
- "(assistant)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Domains.
|
||||
"product / domains":
|
||||
- "(domain|dns|ssl|certificate)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Locale.
|
||||
"product / locale":
|
||||
- "(locale|i18n|internationalization|localization|l10n|translation|timezone|country)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite Avatars.
|
||||
"product / avatars":
|
||||
- "(avatar|initial|flag|icon)"
|
||||
|
||||
# Fixes and upgrades for Appwrite Sites.
|
||||
"product / sites":
|
||||
- "(site|web|hosting|domain|ssl|certificate|nextjs|nuxt|react|angular|vue|svelte|astro)"
|
||||
|
||||
# Fixes and upgrades for the Appwrite CLI.
|
||||
"sdk / cli":
|
||||
- "(cli|command line)"
|
||||
|
||||
# Issues only found when self-hosting Appwrite
|
||||
"product / self-hosted":
|
||||
- "(self-host|self host)"
|
||||
@@ -1,32 +0,0 @@
|
||||
name: AI Moderator
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
issue_comment:
|
||||
types: [created, edited]
|
||||
pull_request:
|
||||
types: [opened, edited]
|
||||
pull_request_review:
|
||||
types: [submitted, edited]
|
||||
pull_request_review_comment:
|
||||
types: [created, edited]
|
||||
discussion:
|
||||
types: [created, edited]
|
||||
discussion_comment:
|
||||
types: [created, edited]
|
||||
|
||||
permissions:
|
||||
models: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
discussions: write
|
||||
|
||||
jobs:
|
||||
moderate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: AI Moderator
|
||||
uses: github/ai-moderator@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,22 +0,0 @@
|
||||
name: Auto Label Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Issue Labeler
|
||||
uses: github/issue-labeler@v3.4
|
||||
with:
|
||||
configuration-path: .github/labeler.yml
|
||||
enable-versioned-regex: false
|
||||
include-title: 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,123 +0,0 @@
|
||||
name: Benchmark
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.ref }}'
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
IMAGE: appwrite-dev
|
||||
CACHE_KEY: 'appwrite-dev-${{ github.event.pull_request.head.sha }}'
|
||||
'on':
|
||||
- pull_request
|
||||
jobs:
|
||||
setup:
|
||||
name: Setup & Build Appwrite Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build Appwrite
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
tags: '${{ env.IMAGE }}'
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
cache-to: 'type=gha,mode=max'
|
||||
outputs: 'type=docker,dest=/tmp/${{ env.IMAGE }}.tar'
|
||||
target: development
|
||||
build-args: |
|
||||
DEBUG=false
|
||||
TESTING=true
|
||||
VERSION=dev
|
||||
- name: Cache Docker Image
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: '${{ env.CACHE_KEY }}'
|
||||
path: '/tmp/${{ env.IMAGE }}.tar'
|
||||
benchmarking:
|
||||
name: Benchmark
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: '${{ env.CACHE_KEY }}'
|
||||
path: '/tmp/${{ env.IMAGE }}.tar'
|
||||
fail-on-cache-miss: true
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
sed -i 's/traefik/localhost/g' .env
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Install Oha
|
||||
run: |
|
||||
echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list
|
||||
sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg
|
||||
sudo apt update
|
||||
sudo apt install oha
|
||||
oha --version
|
||||
- name: Benchmark PR
|
||||
run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json'
|
||||
- name: Cleaning
|
||||
run: docker compose down -v
|
||||
- name: Installing latest version
|
||||
run: |
|
||||
rm docker-compose.yml
|
||||
rm .env
|
||||
curl https://appwrite.io/install/compose -o docker-compose.yml
|
||||
curl https://appwrite.io/install/env -o .env
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=enabled/_APP_OPTIONS_ABUSE=disabled/g' .env
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Benchmark Latest
|
||||
run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json
|
||||
- name: Prepare comment
|
||||
run: |
|
||||
echo '## :sparkles: Benchmark results' > benchmark.txt
|
||||
echo ' ' >> benchmark.txt
|
||||
echo "- Requests per second: $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- Requests with 200 status code: $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- P99 latency: $(jq -r '.latencyPercentiles.p99' benchmark.json )" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "## :zap: Benchmark Comparison" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "| Metric | This PR | Latest version | " >> benchmark.txt
|
||||
echo "| --- | --- | --- | " >> benchmark.txt
|
||||
echo "| RPS | $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.summary.requestsPerSec|tonumber|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt
|
||||
echo "| 200 | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt
|
||||
echo "| P99 | $(jq -r '.latencyPercentiles.p99' benchmark.json ) | $(jq -r '.latencyPercentiles.p99' benchmark-latest.json ) | " >> benchmark.txt
|
||||
- name: Save results
|
||||
uses: actions/upload-artifact@v6
|
||||
if: '${{ !cancelled() }}'
|
||||
with:
|
||||
name: benchmark.json
|
||||
path: benchmark.json
|
||||
retention-days: 7
|
||||
- name: Find Comment
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: '${{ github.event.pull_request.number }}'
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Benchmark results
|
||||
- name: Comment on PR
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
comment-id: '${{ steps.fc.outputs.comment-id }}'
|
||||
issue-number: '${{ github.event.pull_request.number }}'
|
||||
body-path: benchmark.txt
|
||||
edit-mode: replace
|
||||
@@ -1,19 +0,0 @@
|
||||
name: Check dependencies
|
||||
|
||||
# Adapted from https://google.github.io/osv-scanner/github-action/#scan-on-pull-request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, 1.*.x]
|
||||
merge_group:
|
||||
branches: [main, 1.*.x]
|
||||
|
||||
permissions:
|
||||
# Require writing security events to upload SARIF file to security tab
|
||||
security-events: write
|
||||
# Only need to read contents
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
scan-pr:
|
||||
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v1.7.1"
|
||||
@@ -1,39 +0,0 @@
|
||||
name: Cleanup Cache
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||
|
||||
while true
|
||||
do
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
|
||||
|
||||
if [ -z "$cacheKeysForPR" ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
done
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,9 +1,5 @@
|
||||
name: "CodeQL"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
@@ -13,13 +9,8 @@ on:
|
||||
schedule:
|
||||
- cron: '0 16 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
permissions:
|
||||
security-events: write
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -34,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -47,14 +38,14 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -68,4 +59,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,115 +0,0 @@
|
||||
---
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # Run daily at midnight UTC
|
||||
workflow_dispatch: # Enable manual trigger
|
||||
stop-after: +30d # workflow will no longer trigger after 30 days. Remove this and recompile to run indefinitely
|
||||
reaction: eyes
|
||||
|
||||
permissions: read-all
|
||||
|
||||
# Add stricter error-detection patterns so issue text doesn't trigger agent error detection.
|
||||
# After merging this file run `gh aw compile` to regenerate the lock file.
|
||||
env:
|
||||
GH_AW_ERROR_PATTERNS: >-
|
||||
[
|
||||
{"id":"gh-action-error","pattern":"^::(error)(?:\\\\s+[^:]*)?::(.+)","level_group":1,"message_group":2,"description":"GitHub Actions workflow command - error"},
|
||||
{"id":"gh-action-warning","pattern":"^::(warning)(?:\\\\s+[^:]*)?::(.+)","level_group":1,"message_group":2,"description":"GitHub Actions workflow command - warning"},
|
||||
{"id":"bracketed-level","pattern":"^\\[(ERROR|CRITICAL|WARNING|WARN)\\]\\s+(.+)","level_group":1,"message_group":2,"description":"Bracketed log level at start of line"},
|
||||
{"id":"timestamped-copilot","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z\\s+\\[(ERROR|WARN|WARNING|CRITICAL)\\]\\s+(.+)","level_group":1,"message_group":3,"description":"Timestamped Copilot CLI messages"}
|
||||
]
|
||||
|
||||
network: defaults
|
||||
|
||||
safe-outputs:
|
||||
add-labels:
|
||||
max: 100
|
||||
target: "*"
|
||||
add-comment:
|
||||
max: 10
|
||||
target: "*"
|
||||
|
||||
tools:
|
||||
web-fetch:
|
||||
web-search:
|
||||
github:
|
||||
toolsets:
|
||||
- default
|
||||
- labels
|
||||
|
||||
timeout-minutes: 10
|
||||
source: githubnext/agentics/workflows/issue-triage.md@0837fb7b24c3b84ee77fb7c8cfa8735c48be347a
|
||||
---
|
||||
# Agentic Triage
|
||||
|
||||
<!-- Note - this file can be customized to your needs. Replace this section directly, or add further instructions here. After editing run 'gh aw compile' -->
|
||||
|
||||
You're a triage assistant for GitHub issues. Your task is to analyze issues that were either created in the last 24 hours or updated (with a new comment) in the last 24 hours, and perform initial triage tasks for each of them.
|
||||
|
||||
1. First, use the `list_issues` tool to retrieve all issues created or updated in the last 24 hours. The `since` parameter filters by the issue's `updated_at` timestamp, which includes both newly created issues and recently commented issues. Calculate the timestamp from 24 hours ago (example: 2025-11-06T20:27:14Z for reference) and use it for the `since` parameter.
|
||||
|
||||
2. For each issue found, perform the following triage tasks:
|
||||
|
||||
3. Use the `get_comments` tool to retrieve all the comments on the issue.
|
||||
|
||||
4. Check for spam and quality issue descriptions and comments first:
|
||||
|
||||
- **Non-English Content**: If the issue is primarily written in a non-English language, add a respectful and appreciative comment explaining that while you appreciate their contribution, the majority of the community communicates in English and kindly ask them to repost in English so everyone can follow along and help. Provide a friendly translation of your message in their language if possible.
|
||||
- **Multiple Topics**: If the issue discusses multiple unrelated topics or problems, add a comment explaining that each issue should focus on one clear topic so the team can effectively solve the right problem. Politely ask them to split it into separate issues.
|
||||
- **Obvious Spam or Bot-Generated Content**: If the issue/comment is obviously spam, generated by a bot, or something that is not an actual issue to be worked on, add an issue comment with a one-sentence analysis and move to the next issue.
|
||||
|
||||
5. Retrieve the issue content using the `get_issue` tool for any issues that pass the spam checks.
|
||||
|
||||
6. Next, use the GitHub tools to gather additional context about the issue:
|
||||
|
||||
- Fetch the list of labels available in this repository using the `list_label` tool with `owner: "appwrite"` and `repo: "appwrite"` parameters. This will give you the labels you can use for triaging issues.
|
||||
- Fetch any comments on the issue using the `get_issue_comments` tool to understand recent activity
|
||||
- **Search for duplicate and related issues (repo first, then org-wide)**:
|
||||
- First search in this repository using the `search_issues` tool with a query like: `repo:appwrite/appwrite is:issue (is:open OR is:closed) <key terms>`.
|
||||
- Then perform an org-wide search across the entire Appwrite organization using: `org:appwrite is:issue (is:open OR is:closed) <key terms>`.
|
||||
- Prefer linking to OPEN issues when identifying potential duplicates; include CLOSED ones as related history when useful.
|
||||
|
||||
7. Analyze the issue content, considering:
|
||||
|
||||
- The issue title and description
|
||||
- The type of issue (bug report, feature request, question, etc.)
|
||||
- Technical areas mentioned
|
||||
- Severity or priority indicators
|
||||
- User impact
|
||||
- Components affected
|
||||
|
||||
8. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
|
||||
|
||||
9. Select appropriate labels from the available labels list:
|
||||
|
||||
- Choose labels that accurately reflect the issue's nature
|
||||
- Be specific but comprehensive
|
||||
- Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority)
|
||||
- Consider platform labels (android, ios) if applicable
|
||||
- Search for similar issues. If you find a duplicate of another OPEN issue in THIS repository, you may use a "duplicate" label (if available) and reference the canonical issue.
|
||||
- If the closest match is in another repository within the Appwrite org, do NOT mark as duplicate here; instead, link it in your comment under a "Cross‑repo related issues" section.
|
||||
- Only select labels from the provided list
|
||||
- Don't apply the `good first issue` or `help wanted` labels
|
||||
- It's okay to not add any labels if none are clearly applicable
|
||||
|
||||
10. Apply the selected labels:
|
||||
|
||||
- Use the `update_issue` tool to apply the labels to the issue
|
||||
- DO NOT communicate directly with users
|
||||
- If no labels are clearly applicable, do not apply any labels
|
||||
|
||||
11. Add an issue comment to the issue with your analysis:
|
||||
- Start with "🎯 Agentic Issue Triage"
|
||||
- Provide a brief summary of the issue
|
||||
- **If duplicate or related issues were found**, add sections listing them with links:
|
||||
- "### 🔗 Potentially Related Issues (this repo)" – bullet list of same-repo issues with titles and links
|
||||
- If applicable: "### 🌐 Cross-repo related issues (org: appwrite)" – bullet list including `owner/repo#number` with titles and links
|
||||
- Mention any relevant details that might help the team understand the issue better
|
||||
- Include any debugging strategies or reproduction steps if applicable
|
||||
- Suggest resources or links that might be helpful for resolving the issue or learning skills related to the issue or the particular area of the codebase affected by it
|
||||
- Mention any nudges or ideas that could help the team in addressing the issue
|
||||
- If appropriate break the issue down to sub-tasks and write a checklist of things to do
|
||||
- Use collapsed-by-default sections in the GitHub markdown to keep the comment tidy. Collapse all sections except the short main summary at the top. For bolded section titles, wrap the text with `<strong>` and `</strong>` to make it bold.
|
||||
- Do not indicate/encourage a community member to submit a PR for the issue.
|
||||
|
||||
12. After processing all issues, provide a summary of how many issues were triaged (created or updated in the last 24 hours). If no issues matched the criteria, simply note that no issues needed triage.
|
||||
@@ -1,9 +1,5 @@
|
||||
name: "Linter"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
lint:
|
||||
@@ -12,17 +8,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- run: git checkout HEAD^2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
"composer validate"
|
||||
- name: Run Linter
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
docker run --rm -v $PWD:/app composer sh -c \
|
||||
"composer install --profile --ignore-platform-reqs && composer lint"
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Nightly Security Scan
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # 12am UTC daily runtime
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
scan-image:
|
||||
name: Scan Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build the Docker image
|
||||
run: DOCKER_BUILDKIT=1 docker build . --target production -t appwrite_image:latest
|
||||
- name: Run Trivy vulnerability scanner on image
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
image-ref: 'appwrite_image:latest'
|
||||
format: 'sarif'
|
||||
output: 'trivy-image-results.sarif'
|
||||
ignore-unfixed: 'false'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
- name: Upload Docker Image Scan Results
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-image-results.sarif'
|
||||
|
||||
scan-code:
|
||||
name: Scan Code
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
- name: Run Trivy vulnerability scanner on filesystem
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
format: 'sarif'
|
||||
output: 'trivy-fs-results.sarif'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
- name: Upload Code Scan Results
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-fs-results.sarif'
|
||||
@@ -1,106 +0,0 @@
|
||||
name: PR Security Scan
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
scan:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Build the Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
load: true
|
||||
tags: pr_image:${{ github.sha }}
|
||||
target: production
|
||||
|
||||
- name: Run Trivy vulnerability scanner on image
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
image-ref: 'pr_image:${{ github.sha }}'
|
||||
format: 'json'
|
||||
output: 'trivy-image-results.json'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
- name: Run Trivy vulnerability scanner on source code
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'json'
|
||||
output: 'trivy-fs-results.json'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
- name: Process Trivy scan results
|
||||
id: process-results
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
let commentBody = '## Security Scan Results for PR\n\n';
|
||||
|
||||
function processResults(results, title) {
|
||||
let sectionBody = `### ${title}\n\n`;
|
||||
if (results.Results && results.Results.some(result => result.Vulnerabilities && result.Vulnerabilities.length > 0)) {
|
||||
sectionBody += '| Package | Version | Vulnerability | Severity |\n';
|
||||
sectionBody += '|---------|---------|----------------|----------|\n';
|
||||
|
||||
const uniqueVulns = new Set();
|
||||
results.Results.forEach(result => {
|
||||
if (result.Vulnerabilities) {
|
||||
result.Vulnerabilities.forEach(vuln => {
|
||||
const vulnKey = `${vuln.PkgName}-${vuln.InstalledVersion}-${vuln.VulnerabilityID}`;
|
||||
if (!uniqueVulns.has(vulnKey)) {
|
||||
uniqueVulns.add(vulnKey);
|
||||
sectionBody += `| ${vuln.PkgName} | ${vuln.InstalledVersion} | [${vuln.VulnerabilityID}](https://nvd.nist.gov/vuln/detail/${vuln.VulnerabilityID}) | ${vuln.Severity} |\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sectionBody += '🎉 No vulnerabilities found!\n';
|
||||
}
|
||||
return sectionBody;
|
||||
}
|
||||
|
||||
try {
|
||||
const imageResults = JSON.parse(fs.readFileSync('trivy-image-results.json', 'utf8'));
|
||||
const fsResults = JSON.parse(fs.readFileSync('trivy-fs-results.json', 'utf8'));
|
||||
|
||||
commentBody += processResults(imageResults, "Docker Image Scan Results");
|
||||
commentBody += '\n';
|
||||
commentBody += processResults(fsResults, "Source Code Scan Results");
|
||||
|
||||
} catch (error) {
|
||||
commentBody += `There was an error while running the security scan: ${error.message}\n`;
|
||||
commentBody += 'Please contact the core team for assistance.';
|
||||
}
|
||||
|
||||
core.setOutput('comment-body', commentBody);
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Security Scan Results for PR
|
||||
|
||||
- name: Create or update comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
body: ${{ steps.process-results.outputs.comment-body }}
|
||||
edit-mode: replace
|
||||
@@ -1,52 +0,0 @@
|
||||
name: "Build and Publish Appwrite Images for Cloud"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- cl-*
|
||||
|
||||
jobs:
|
||||
build-publish:
|
||||
name: Build and Publish
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 2
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: appwrite/cloud
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build & Publish to DockerHub
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: production
|
||||
build-args: |
|
||||
VERSION=${{ steps.meta.outputs.version }}
|
||||
VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
|
||||
VITE_GA_PROJECT=G-L7G2B6PLDS
|
||||
VITE_CONSOLE_MODE=cloud
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
@@ -1,54 +0,0 @@
|
||||
name: "Release"
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
# Fetch submodules
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: appwrite/appwrite
|
||||
tags: |
|
||||
type=semver,pattern={{major}}.{{minor}}.{{patch}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: production
|
||||
build-args: |
|
||||
VERSION=${{ steps.meta.outputs.version }}
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -1,61 +0,0 @@
|
||||
name: "SDK Preview"
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
platform:
|
||||
type: choice
|
||||
description: "Platform to build"
|
||||
options:
|
||||
- client
|
||||
- server
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
name: Setup & Build SDK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set SDK type
|
||||
id: set-sdk
|
||||
run: |
|
||||
PLATFORM="${{ github.event.inputs.platform }}"
|
||||
if [ -z "$PLATFORM" ]; then
|
||||
PLATFORM="console"
|
||||
fi
|
||||
if [ "$PLATFORM" = "server" ]; then
|
||||
echo "sdk_type=nodejs" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "sdk_type=web" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "platform=$PLATFORM" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
||||
- name: Generate Specs
|
||||
run: |
|
||||
docker compose exec appwrite specs --version=latest --mode=normal --git=no
|
||||
|
||||
- name: Generate SDK
|
||||
run: |
|
||||
docker compose exec appwrite sdks --platform=${{ steps.set-sdk.outputs.platform }} --sdk=${{ steps.set-sdk.outputs.sdk_type }} --version=latest --git=no
|
||||
sudo chown -R $USER:$USER ./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }}
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Build and Publish SDK
|
||||
working-directory: ./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }}
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
npx pkg-pr-new publish --comment=update
|
||||
@@ -1,113 +0,0 @@
|
||||
name: "Generate Specs"
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
type: choice
|
||||
description: "Appwrite version to generate specs for"
|
||||
required: true
|
||||
options:
|
||||
- "1.8.x"
|
||||
- "1.7.x"
|
||||
- "1.6.x"
|
||||
- "1.5.x"
|
||||
- "latest"
|
||||
push:
|
||||
type: boolean
|
||||
description: "Push specs to appwrite/specs repo and create PR"
|
||||
default: true
|
||||
message:
|
||||
type: string
|
||||
description: "Commit message for the specs PR"
|
||||
default: "chore: update API specs and SDK examples"
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate Specs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build and start Appwrite
|
||||
run: |
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
||||
- name: Generate specs
|
||||
run: |
|
||||
docker compose exec appwrite specs --version=${{ inputs.version }} --mode=normal --git=no
|
||||
|
||||
- name: Generate SDK examples
|
||||
if: inputs.push
|
||||
run: |
|
||||
docker compose exec appwrite sdks --platform=* --sdk=* --version=${{ inputs.version }} --git=no --mode=examples
|
||||
sudo chown -R $USER:$USER ./docs/examples/
|
||||
|
||||
- name: Push to appwrite/specs and create PR
|
||||
if: inputs.push
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ inputs.version }}"
|
||||
MESSAGE="${{ inputs.message }}"
|
||||
GIT_BRANCH="feat-${VERSION}-specs"
|
||||
SPECS_DIR="./app/config/specs"
|
||||
EXAMPLES_DIR="./docs/examples/${VERSION}"
|
||||
TARGET="/tmp/specs-repo"
|
||||
|
||||
sudo chown -R $USER:$USER "${SPECS_DIR}"
|
||||
|
||||
# Clone the specs repo
|
||||
git clone "https://x-access-token:${GH_TOKEN}@github.com/appwrite/specs.git" "${TARGET}"
|
||||
cd "${TARGET}"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Create or checkout the feature branch
|
||||
git checkout -b "${GIT_BRANCH}" || git checkout "${GIT_BRANCH}"
|
||||
|
||||
# Copy spec files
|
||||
mkdir -p "specs/${VERSION}"
|
||||
cp ${GITHUB_WORKSPACE}/${SPECS_DIR}/*${VERSION}*.json "specs/${VERSION}/" 2>/dev/null || true
|
||||
|
||||
# Copy latest specs if version is latest
|
||||
if [ "${VERSION}" = "latest" ]; then
|
||||
cp ${GITHUB_WORKSPACE}/${SPECS_DIR}/*latest*.json "specs/latest/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Copy SDK examples
|
||||
if [ -d "${GITHUB_WORKSPACE}/docs/examples/${VERSION}" ]; then
|
||||
mkdir -p "examples/${VERSION}"
|
||||
cp -r "${GITHUB_WORKSPACE}/docs/examples/${VERSION}/." "examples/${VERSION}/"
|
||||
fi
|
||||
|
||||
# Commit and push
|
||||
git add -A
|
||||
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
||||
git commit -m "${MESSAGE}"
|
||||
git push -u origin "${GIT_BRANCH}" --force
|
||||
|
||||
# Create or update PR
|
||||
EXISTING_PR=$(gh pr list --repo appwrite/specs --head "${GIT_BRANCH}" --json number --jq '.[0].number' 2>/dev/null || true)
|
||||
if [ -n "${EXISTING_PR}" ]; then
|
||||
echo "PR #${EXISTING_PR} already exists, updated branch"
|
||||
echo "https://github.com/appwrite/specs/pull/${EXISTING_PR}"
|
||||
else
|
||||
gh pr create \
|
||||
--repo "appwrite/specs" \
|
||||
--title "feat: API specs update for version ${VERSION}" \
|
||||
--body "This PR contains API specification updates and SDK examples for version ${VERSION}." \
|
||||
--base "main" \
|
||||
--head "${GIT_BRANCH}"
|
||||
fi
|
||||
|
||||
- name: Stop containers
|
||||
if: always()
|
||||
run: docker compose down
|
||||
@@ -1,23 +0,0 @@
|
||||
name: Mark stale issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Midnight Runtime
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: "This issue has been labeled as a 'question', indicating that it requires additional information from the requestor. It has been inactive for 7 days. If no further activity occurs, this issue will be closed in 14 days."
|
||||
stale-issue-label: "stale"
|
||||
days-before-stale: 7
|
||||
days-before-close: 14
|
||||
remove-stale-when-updated: true
|
||||
close-issue-message: "This issue has been closed due to inactivity. If you still require assistance, please provide the requested information."
|
||||
close-issue-reason: "not_planned"
|
||||
operations-per-run: 100
|
||||
only-labels: "question"
|
||||
@@ -1,21 +0,0 @@
|
||||
name: "Static code analysis"
|
||||
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
lint:
|
||||
name: CodeQL
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Run CodeQL
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
"composer install --profile --ignore-platform-reqs && composer check"
|
||||
|
||||
- name: Run Locale check
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app node:24-alpine sh -c \
|
||||
"cd /app/.github/workflows/static-analysis/locale && node index.js"
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Look into all local files, and collect unique keys.
|
||||
* Ensure fallback locale (English) has translation for all keys.
|
||||
* If configured as `const strict = true`, all locales will be checked to include all keys.
|
||||
*/
|
||||
|
||||
import { readdir, readFile } from "fs/promises";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const config = {
|
||||
strict: false,
|
||||
fallbackLocale: "en.json",
|
||||
};
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// Prepare current directory equivalent in ES modules
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const translationsPath = join(
|
||||
__dirname,
|
||||
"../../../../app/config/locale/translations",
|
||||
);
|
||||
|
||||
const files = (await readdir(translationsPath)).filter((file) =>
|
||||
file.endsWith(".json"),
|
||||
);
|
||||
|
||||
if (files.length === 0) {
|
||||
console.error("No translation files found in ", translationsPath);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if fallback locale exists
|
||||
if (!files.includes(config.fallbackLocale)) {
|
||||
console.error(`Fallback locale file ${config.fallbackLocale} not found`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Found ${files.length} translation files in ${translationsPath}`,
|
||||
);
|
||||
|
||||
// Collect all unique keys from all translation files
|
||||
const allKeys = new Set();
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = join(translationsPath, file);
|
||||
const content = await readFile(filePath, "utf8");
|
||||
const translations = JSON.parse(content);
|
||||
|
||||
// Add all keys from this file
|
||||
Object.keys(translations).forEach((key) => allKeys.add(key));
|
||||
}
|
||||
|
||||
console.log(`Total unique keys found across all locales: ${allKeys.size}`);
|
||||
|
||||
const localesToCheck = [];
|
||||
if (config.strict) {
|
||||
localesToCheck.push(...files);
|
||||
} else {
|
||||
localesToCheck.push(config.fallbackLocale);
|
||||
}
|
||||
|
||||
let errorsCount = 0;
|
||||
let missingLocaleCount = 0;
|
||||
|
||||
for (const localeToCheck of localesToCheck) {
|
||||
// Read locale
|
||||
const path = join(translationsPath, localeToCheck);
|
||||
const content = await readFile(path, "utf8");
|
||||
const translations = JSON.parse(content);
|
||||
|
||||
// Check for missing keys in the locale
|
||||
const keys = new Set(Object.keys(translations));
|
||||
console.log(`Keys in locale (${localeToCheck}): ${keys.size}`);
|
||||
|
||||
const missingKeys = [];
|
||||
for (const key of allKeys) {
|
||||
if (!keys.has(key)) {
|
||||
missingKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingKeys.length > 0) {
|
||||
console.error(
|
||||
`\nERROR: Fallback locale (${localeToCheck}) is missing ${missingKeys.length} key(s):`,
|
||||
);
|
||||
missingKeys.sort().forEach((key) => {
|
||||
console.error(` - ${key}`);
|
||||
});
|
||||
console.error(
|
||||
`\nTo fix this issue, add the missing keys to ${translationsPath}/${localeToCheck}`,
|
||||
);
|
||||
errorsCount++;
|
||||
missingLocaleCount += missingKeys.length;
|
||||
} else {
|
||||
console.log(
|
||||
`\nSUCCESS: Fallback locale (${localeToCheck}) contains all ${allKeys.size} keys.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorsCount > 0) {
|
||||
console.log(`\n${missingLocaleCount} locales missing found across ${errorsCount} locales.`);
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Unexpected error.");
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "static-analysis-locale",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": ""
|
||||
}
|
||||
+31
-681
@@ -1,691 +1,41 @@
|
||||
name: "Tests"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
IMAGE: appwrite-dev
|
||||
CACHE_KEY: appwrite-dev-${{ github.event.pull_request.head.sha }}
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
response_format:
|
||||
description: 'Response format version to test (e.g., 1.5.0, 1.4.0)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
check_database_changes:
|
||||
name: Check if utopia-php/database changed
|
||||
tests:
|
||||
name: Unit & E2E
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
database_changed: ${{ steps.check.outputs.database_changed }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Fetch base branch
|
||||
run: git fetch origin ${{ github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Check for utopia-php/database changes
|
||||
id: check
|
||||
run: |
|
||||
if git diff origin/${{ github.event.pull_request.base.ref }} HEAD -- composer.lock | grep -q '"name": "utopia-php/database"'; then
|
||||
echo "Database version changed, going to run all mode tests."
|
||||
echo "database_changed=true" >> "$GITHUB_ENV"
|
||||
echo "database_changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "database_changed=false" >> "$GITHUB_ENV"
|
||||
echo "database_changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
setup:
|
||||
name: Setup & Build Appwrite Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build Appwrite
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
tags: ${{ env.IMAGE }}
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
outputs: type=docker,dest=/tmp/${{ env.IMAGE }}.tar
|
||||
target: development
|
||||
build-args: |
|
||||
DEBUG=false
|
||||
TESTING=true
|
||||
VERSION=dev
|
||||
|
||||
- name: Cache Docker Image
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
|
||||
unit_test:
|
||||
name: Unit Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
- name: Build Appwrite
|
||||
# Upstream bug causes buildkit pulls to fail so prefetch base images
|
||||
# https://github.com/moby/moby/issues/41864
|
||||
run: |
|
||||
export COMPOSE_INTERACTIVE_NO_CLI
|
||||
export DOCKER_BUILDKIT=1
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
||||
export BUILDKIT_PROGRESS=plain
|
||||
docker pull composer:2.0
|
||||
docker compose build appwrite
|
||||
docker compose up -d
|
||||
sleep 30
|
||||
- name: Doctor
|
||||
run: docker compose exec -T appwrite doctor
|
||||
|
||||
- name: Environment Variables
|
||||
run: docker compose exec -T appwrite vars
|
||||
- name: Environment Variables
|
||||
run: docker compose exec -T appwrite vars
|
||||
|
||||
- name: Run Unit Tests
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/unit
|
||||
command: >-
|
||||
docker compose exec
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
|
||||
appwrite test /usr/src/code/tests/unit
|
||||
|
||||
e2e_general_test:
|
||||
name: E2E General Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run General Tests
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/General
|
||||
command: >-
|
||||
docker compose exec -T
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
|
||||
appwrite test /usr/src/code/tests/e2e/General --debug
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Logs ==="
|
||||
docker compose logs
|
||||
|
||||
e2e_service_test:
|
||||
name: E2E Service Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
db_adapter: [
|
||||
MARIADB,
|
||||
POSTGRESQL,
|
||||
MONGODB
|
||||
]
|
||||
service: [
|
||||
Account,
|
||||
Avatars,
|
||||
Console,
|
||||
Databases,
|
||||
Functions,
|
||||
FunctionsSchedule,
|
||||
GraphQL,
|
||||
Health,
|
||||
Locale,
|
||||
Projects,
|
||||
Realtime,
|
||||
Sites,
|
||||
Proxy,
|
||||
Storage,
|
||||
Tokens,
|
||||
Teams,
|
||||
Users,
|
||||
Webhooks,
|
||||
VCS,
|
||||
Messaging,
|
||||
Migrations
|
||||
]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Set DB Adapter environment
|
||||
id: set-db-env
|
||||
run: |
|
||||
DB_ADAPTER_LOWER=$(echo "${{ matrix.db_adapter }}" | tr 'A-Z' 'a-z')
|
||||
echo "COMPOSE_PROFILES=${DB_ADAPTER_LOWER}" >> $GITHUB_ENV
|
||||
|
||||
if [ "${{ matrix.db_adapter }}" = "MARIADB" ]; then
|
||||
echo "_APP_DB_ADAPTER=mariadb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=mariadb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=3306" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.db_adapter }}" = "MONGODB" ]; then
|
||||
echo "_APP_DB_ADAPTER=mongodb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=mongodb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=27017" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.db_adapter }}" = "POSTGRESQL" ]; then
|
||||
echo "_APP_DB_ADAPTER=postgresql" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=postgresql" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=5432" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
env:
|
||||
_APP_BROWSER_HOST: http://invalid-browser/v1
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run ${{ matrix.service }} tests with Project table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 20
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/${{ matrix.service }}
|
||||
command: |
|
||||
echo "Using project tables"
|
||||
SERVICE_PATH="/usr/src/code/tests/e2e/Services/${{ matrix.service }}"
|
||||
|
||||
# Services that rely on sequential test method execution (shared static state)
|
||||
FUNCTIONAL_FLAG="--functional"
|
||||
case "${{ matrix.service }}" in
|
||||
Databases|Functions|Realtime) FUNCTIONAL_FLAG="" ;;
|
||||
esac
|
||||
|
||||
echo "Running with paratest (parallel) for: ${{ matrix.service }} ${FUNCTIONAL_FLAG:+(functional)}"
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES="" \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1="" \
|
||||
-e _APP_DB_ADAPTER="${{ env._APP_DB_ADAPTER }}" \
|
||||
-e _APP_DB_HOST="${{ env._APP_DB_HOST }}" \
|
||||
-e _APP_DB_PORT="${{ env._APP_DB_PORT }}" \
|
||||
-e _APP_DB_SCHEMA=appwrite \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) $FUNCTIONAL_FLAG "$SERVICE_PATH" --exclude-group abuseEnabled --exclude-group screenshots --exclude-group ciIgnore --log-junit tests/e2e/Services/${{ matrix.service }}/junit.xml
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Logs ==="
|
||||
docker compose logs
|
||||
|
||||
e2e_shared_mode_test:
|
||||
name: E2E Shared Mode Service Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
service:
|
||||
[
|
||||
Account,
|
||||
Avatars,
|
||||
Console,
|
||||
Databases,
|
||||
Functions,
|
||||
FunctionsSchedule,
|
||||
GraphQL,
|
||||
Health,
|
||||
Locale,
|
||||
Projects,
|
||||
Realtime,
|
||||
Sites,
|
||||
Proxy,
|
||||
Storage,
|
||||
Teams,
|
||||
Users,
|
||||
Webhooks,
|
||||
VCS,
|
||||
Messaging,
|
||||
Migrations,
|
||||
Tokens
|
||||
]
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
'Shared V2',
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 20
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/${{ matrix.service }}
|
||||
command: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
SERVICE_PATH="/usr/src/code/tests/e2e/Services/${{ matrix.service }}"
|
||||
|
||||
# Services that rely on sequential test method execution (shared static state)
|
||||
FUNCTIONAL_FLAG="--functional"
|
||||
case "${{ matrix.service }}" in
|
||||
Databases|Functions|Realtime) FUNCTIONAL_FLAG="" ;;
|
||||
esac
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) $FUNCTIONAL_FLAG "$SERVICE_PATH" --exclude-group abuseEnabled --exclude-group screenshots --exclude-group ciIgnore --log-junit tests/e2e/Services/${{ matrix.service }}/junit.xml
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
|
||||
e2e_abuse_enabled:
|
||||
name: E2E Service Test (Abuse enabled)
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Run Projects tests in dedicated table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Projects
|
||||
command: |
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=abuseEnabled
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
|
||||
e2e_abuse_enabled_shared_mode:
|
||||
name: E2E Shared Mode Service Test (Abuse enabled)
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
'Shared V2',
|
||||
]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Run Projects tests in ${{ matrix.tables-mode }} table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Projects
|
||||
command: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=abuseEnabled
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
|
||||
e2e_screenshots:
|
||||
name: E2E Service Test (Site Screenshots)
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run Site tests with browser connected in dedicated table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Sites
|
||||
command: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Sites --debug --group=screenshots
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
|
||||
e2e_screenshots_shared_mode:
|
||||
name: E2E Shared Mode Service Test (Site Screenshots)
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
'Shared V2',
|
||||
]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
until docker compose exec -T appwrite doctor > /dev/null 2>&1; do
|
||||
echo "Waiting for Appwrite to be ready..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run Site tests with browser connected in ${{ matrix.tables-mode }} table mode
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 2
|
||||
retry_wait_seconds: 300
|
||||
timeout_minutes: 15
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Sites
|
||||
command: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Sites --debug --group=screenshots
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
- name: Run Tests
|
||||
run: docker compose exec -T appwrite test --debug
|
||||
|
||||
-10
@@ -3,21 +3,11 @@
|
||||
/node_modules/
|
||||
/tests/resources/storage/
|
||||
/tests/resources/functions/**/code.tar.gz
|
||||
/tests/resources/sites/**/code.tar.gz
|
||||
/app/sdks/*
|
||||
/.idea/
|
||||
!/.idea/workspace.xml
|
||||
!/.idea/php.xml
|
||||
.DS_Store
|
||||
.php_cs.cache
|
||||
.phpactor.json
|
||||
debug/
|
||||
app/sdks
|
||||
dev/yasd_init.php
|
||||
.phpunit.result.cache
|
||||
Makefile
|
||||
appwrite.config.json
|
||||
/.zed/
|
||||
/app/config/specs/
|
||||
/docs/examples/
|
||||
.phpunit.cache
|
||||
|
||||
+11
-4
@@ -1,15 +1,13 @@
|
||||
tasks:
|
||||
- name: Run Appwrite Docker Stack
|
||||
init: |
|
||||
git submodule update --init
|
||||
docker compose build
|
||||
docker compose pull
|
||||
docker compose build
|
||||
docker pull composer
|
||||
command: |
|
||||
docker run --rm --interactive --tty \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--volume $PWD:/app \
|
||||
composer install \
|
||||
composer update \
|
||||
--ignore-platform-reqs \
|
||||
--optimize-autoloader \
|
||||
--no-plugins \
|
||||
@@ -18,9 +16,18 @@ tasks:
|
||||
|
||||
ports:
|
||||
- port: 8080
|
||||
onOpen: open-preview
|
||||
visibility: public
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- ms-azuretools.vscode-docker
|
||||
- zobo.php-intellisense
|
||||
|
||||
github:
|
||||
# https://www.gitpod.io/docs/prebuilds#github-specific-configuration
|
||||
prebuilds:
|
||||
# enable for pull requests coming from forks (defaults to false)
|
||||
pullRequestsFromForks: true
|
||||
# add a check to pull requests (defaults to true)
|
||||
addCheck: false
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# AGENTS.md
|
||||
|
||||
Appwrite is an end-to-end backend server for web, mobile, native, and backend apps. This guide provides context and instructions for AI coding agents working on the Appwrite codebase.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Appwrite is a self-hosted Backend-as-a-Service (BaaS) platform that provides developers with a set of APIs and tools to build secure, scalable applications. The project uses a hybrid monolithic-microservice architecture built with PHP, running on Swoole for high performance.
|
||||
|
||||
**Key Technologies:**
|
||||
- **Backend:** PHP 8.3+, Swoole
|
||||
- **Libraries:** Utopia PHP
|
||||
- **Database:** MariaDB, Redis
|
||||
- **Cache:** Redis
|
||||
- **Queue:** Redis
|
||||
- **Containers:** Docker
|
||||
|
||||
## Development Commands
|
||||
|
||||
```bash
|
||||
# Run Appwrite
|
||||
docker compose up -d --force-recreate --build
|
||||
|
||||
# Run specific test
|
||||
docker compose exec appwrite test /usr/src/code/tests/e2e/Services/[ServiceName] --filter=[FunctionName]
|
||||
|
||||
# Format code
|
||||
composer format
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
- Follow [PSR-12](https://www.php-fig.org/psr/psr-12/) coding standard
|
||||
- Use PSR-4 autoloading
|
||||
- Strict type declarations where applicable
|
||||
- Comprehensive PHPDoc comments
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
#### `resourceType` Naming Rule
|
||||
|
||||
When a collection has a combination of `resourceType`, `resourceId`, and/or `resourceInternalId`, the value of `resourceType` MUST always be **plural** - for example: `functions`, `sites`, `deployments`.
|
||||
|
||||
Examples:
|
||||
```php
|
||||
'resourceType' => 'functions'
|
||||
'resourceType' => 'sites'
|
||||
'resourceType' => 'deployments'
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Critical Security Practices
|
||||
|
||||
- **Never hardcode credentials** - Use environment variables
|
||||
- **Rate limiting** - Respect abuse prevention mechanisms
|
||||
|
||||
## Dependencies
|
||||
|
||||
Avoid introducing new dependencies other than utopia-php.
|
||||
|
||||
## Adding new endpoints
|
||||
|
||||
When adding new endpoints, make sure to use modules and follow its patterns. Find instruction in [Modules AGENTS.md](src/Appwrite/Platform/AGENTS.md) file.
|
||||
|
||||
## Pull Request Guidelines
|
||||
### Before Submitting
|
||||
|
||||
- Run `composer format`
|
||||
- Update documentation if adding features
|
||||
- Add/update tests for your changes
|
||||
- Check that Docker build succeeds
|
||||
`docs/specs/authentication.drawio.svg`
|
||||
|
||||
## Known Issues and Gotchas
|
||||
|
||||
- **Hot Reload:** Code changes require container restart in some cases
|
||||
- **Logging:** There is no central place for logs, so when debugging, ensure to check all possibly relevant containers
|
||||
+1
-1984
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to make participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity, expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at team@appwrite.io. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
+70
-313
@@ -1,45 +1,16 @@
|
||||
# Contributing
|
||||
|
||||
We would :heart: you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, and new docs, as well as updates and tweaks, blog posts, workshops, and more.
|
||||
|
||||
## Here for Hacktoberfest?
|
||||
If you're here to contribute during Hacktoberfest, we're so happy to see you here. Appwrite has been a long-time participant of Hacktoberfest and we welcome you, whatever your experience level. This year, we're **only taking contributions for issues tagged** `hacktoberfest`, so we can focus our resources to support your contributions.
|
||||
|
||||
You can [find issues using this query](https://github.com/search?q=org%3Aappwrite+is%3Aopen+type%3Aissue+label%3Ahacktoberfest&type=issues).
|
||||
We would ❤️ for you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, new docs as well as updates and tweaks, blog posts, workshops, and more.
|
||||
|
||||
## How to Start?
|
||||
|
||||
Welcome! We're excited that you're interested in contributing to Appwrite. To make sure your time is valued and your contributions are successful, please follow these steps before writing any code:
|
||||
|
||||
### 🔍 Step 1: Find an Issue
|
||||
|
||||
Browse open issues and look for ones labeled [good first issue](https://github.com/search?q=org%3Aappwrite+is%3Aopen+type%3Aissue+label%3A%22good+first+issue%22&type=issues) or [help wanted](https://github.com/search?q=org%3Aappwrite+is%3Aopen+type%3Aissue+label%3A%22help+wanted%22&type=issues).
|
||||
|
||||
If you're not sure which issue to pick, ask in our [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) on Discord.
|
||||
|
||||
### 📝 Step 2: Ask to Be Assigned
|
||||
|
||||
Before working on an issue, comment on the GitHub issue asking to be assigned. This prevents multiple people working on the same task.
|
||||
|
||||
Then, create a thread in the [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) on Discord with a link to the issue.
|
||||
|
||||
Our team is small and may not see your GitHub comment right away - posting in the [maintainers channel](https://discord.com/channels/564160730845151244/636852860709240842) ensures it gets seen.
|
||||
|
||||
### 💬 Step 3: Don’t Submit Random PRs
|
||||
|
||||
If you're not working on an assigned issue, create a GitHub issue first.
|
||||
|
||||
PRs submitted without context or discussion may not align with our roadmap and may be closed without review.
|
||||
|
||||
### ⚠️ Please Note
|
||||
|
||||
We’re a very small team managing a large project. Many PRs are submitted, and while we appreciate every effort, we can only review contributions that follow the process above. This helps us keep things fair and organized.
|
||||
If you are worried or don’t know where to start, check out our next section explaining what kind of help we could use and where can you get involved. You can reach out with questions to [Eldad Fux (@eldadfux)](https://twitter.com/eldadfux) or [@appwrite](https://twitter.com/appwrite) on Twitter, and anyone from the [Appwrite team on Discord](https://discord.gg/GSeTUeA). You can also submit an issue, and a maintainer can guide you!
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Help us keep Appwrite open and inclusive. Please read and follow our [Code of Conduct](https://github.com/appwrite/.github/blob/main/CODE_OF_CONDUCT.md).
|
||||
Help us keep Appwrite open and inclusive. Please read and follow our [Code of Conduct](/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Submit a Pull Request :rocket:
|
||||
## Submit a Pull Request 🚀
|
||||
|
||||
Branch naming convention is as following
|
||||
|
||||
@@ -53,13 +24,13 @@ doc-548-submit-a-pull-request-section-to-contribution-guide
|
||||
|
||||
When `TYPE` can be:
|
||||
|
||||
- **feat** - a new feature
|
||||
- **feat** - is a new feature
|
||||
- **doc** - documentation only changes
|
||||
- **cicd** - changes related to CI/CD system
|
||||
- **fix** - a bug fix
|
||||
- **refactor** - code change that neither fixes a bug nor adds a feature
|
||||
|
||||
**All PRs must include a commit message with the description of the changes made!**
|
||||
**All PRs must include a commit message with the changes description!**
|
||||
|
||||
For the initial start, fork the project and use git clone command to download the repository to your computer. A standard procedure for working on an issue would be to:
|
||||
|
||||
@@ -69,27 +40,27 @@ For the initial start, fork the project and use git clone command to do
|
||||
$ git pull
|
||||
```
|
||||
|
||||
2. Create a new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`.<br/>
|
||||
2. Create new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`<br/>
|
||||
|
||||
```
|
||||
$ git checkout -b [name_of_your_new_branch]
|
||||
```
|
||||
|
||||
3. Work - commit - repeat (make sure you're on the correct branch!)
|
||||
3. Work - commit - repeat ( be sure to be in your branch )
|
||||
|
||||
4. Before you push your changes, make sure your code follows the `PSR12` coding standards, which is the standard that Appwrite currently follows. You can easily do this by running the formatter.
|
||||
4. Before you push your changes, make sure your code follows the `PSR12` coding standards , which is the standard Appwrite follows currently. You can easily do this by running the formatter.
|
||||
|
||||
```bash
|
||||
composer format <your file path>
|
||||
```
|
||||
|
||||
Now, go a step further by running the linter using the following command to manually fix the issues the formatter wasn't able to.
|
||||
Now, go a step further by running the linter by the following command to manually fix the issues the formatter wasn't able to fix.
|
||||
|
||||
```bash
|
||||
composer lint <your file path>
|
||||
```
|
||||
|
||||
This will give you a list of errors to rectify. If you need more information on the errors, you can pass in additional command line arguments to get more verbose information. More lists of available arguments can be found [on PHP_Codesniffer usage Wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
|
||||
This will give you a list of errors for you to rectify , if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
|
||||
|
||||
```bash
|
||||
composer lint --report=diff <your file path>
|
||||
@@ -105,23 +76,23 @@ $ git push origin [name_of_your_new_branch]
|
||||
If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button.
|
||||
7. Start a Pull Request
|
||||
Now submit the pull request and click on `Create pull request`.
|
||||
8. Get a code review approval/reject.
|
||||
9. After approval, merge your PR.
|
||||
8. Get a code review approval/reject
|
||||
9. After approval, merge your PR
|
||||
10. GitHub will automatically delete the branch after the merge is done. (they can still be restored).
|
||||
|
||||
## Setup From Source
|
||||
|
||||
To set up a working **development environment**, just fork the project git repository and install the backend and frontend dependencies using the proper package manager and create run the docker-compose stack.
|
||||
|
||||
> If you just want to install Appwrite for day-to-day use and not as a contributor, you can reference the [installation guide](https://github.com/appwrite/appwrite#installation), the [getting started guide](https://appwrite.io/docs/quick-starts), or the main [README](README.md) file.
|
||||
> If you just want to install Appwrite for day-to-day usage and not as a code maintainer use this [installation guide](https://github.com/appwrite/appwrite#installation).
|
||||
|
||||
Please note that these instructions are for setting a functional dev environment. If you want to set up an Appwrite instance to integrate into your app, you should probably try and install Appwrite by using the instructions in the [getting started guide](https://appwrite.io/docs/getting-started-for-web) or in the main [README](README.md) file.
|
||||
|
||||
```bash
|
||||
git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git
|
||||
|
||||
cd appwrite
|
||||
|
||||
git submodule update --init
|
||||
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
@@ -138,9 +109,7 @@ docker run --rm --interactive --tty \
|
||||
|
||||
### User Interface
|
||||
|
||||
Appwrite's UI is built with [Svelte](https://svelte.dev/), [Svelte Kit](https://kit.svelte.dev/), and the [Pink Design](https://github.com/appwrite/pink) component library. You can find the source code in the [Appwrite Console](https://github.com/appwrite/console) repository.
|
||||
|
||||
To contribute to the UI, head to the [Contribution Guide](https://github.com/appwrite/console/blob/main/CONTRIBUTING.md) of Appwrite Console.
|
||||
Appwrite uses an internal micro-framework called Litespeed.js to build simple UI components in vanilla JS and [less](http://lesscss.org/) for compiling CSS code. To apply any of your changes to the UI, use the `gulp build` or `gulp less` commands, and restart the Appwrite main container to load the new static files to memory using `docker compose restart appwrite`.
|
||||
|
||||
### Get Started
|
||||
|
||||
@@ -148,7 +117,7 @@ After finishing the installation process, you can start writing and editing code
|
||||
|
||||
#### Advanced Topics
|
||||
|
||||
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn about the more advanced topics that will help you master the Appwrite codebase.
|
||||
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advance topics that will help you master the Appwrite codebase.
|
||||
|
||||
##### Tools and Libs
|
||||
|
||||
@@ -172,14 +141,6 @@ Learn more at our [Technology Stack](#technology-stack) section.
|
||||
- [Microservices vs Monolithic](https://www.mulesoft.com/resources/api/microservices-vs-monolithic#:~:text=Microservices%20architecture%20vs%20monolithic%20architecture&text=A%20monolithic%20application%20is%20built%20as%20a%20single%20unit.&text=To%20make%20any%20alterations%20to,formally%20with%20business%2Doriented%20APIs.)
|
||||
- [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) - Appwrite console architecture
|
||||
|
||||
##### Container Namespace Conventions
|
||||
To keep our services easy to understand within Docker we follow a naming convention for all our containers depending on it's intended use.
|
||||
|
||||
`appwrite-worker-X` - Workers (`src/Appwrite/Platform/Workers/*`)
|
||||
`appwrite-task-X` - Tasks (`src/Appwrite/Platform/Tasks/*`)
|
||||
|
||||
Other containes should be named the same as their service, for example `redis` should just be called `redis`.
|
||||
|
||||
##### Security
|
||||
|
||||
- [Appwrite Auth and ACL](https://github.com/appwrite/appwrite/blob/master/docs/specs/authentication.drawio.svg)
|
||||
@@ -187,31 +148,9 @@ Other containes should be named the same as their service, for example `redis` s
|
||||
- [Encryption](https://medium.com/searchencrypt/what-is-encryption-how-does-it-work-e8f20e340537#:~:text=Encryption%20is%20a%20process%20that,%2C%20or%20decrypt%2C%20the%20information.)
|
||||
- [Hashing](https://searchsqlserver.techtarget.com/definition/hashing#:~:text=Hashing%20is%20the%20transformation%20of,it%20using%20the%20original%20value.)
|
||||
|
||||
## Modules
|
||||
|
||||
As Appwrite grows, we noticed approach of having all service endpoints in `app/controllers/api/[service].php` is not maintainable. Not only it creates massive files, it also doesnt contain all product's features such as workers or tasks. While there might still be some occurances of those controller files, we avoid it in all new development, and gradually migrate existing controllers to **HTTP modules**.
|
||||
|
||||
### HTTP Endpoints
|
||||
|
||||
Every endpoint file follows below structure, making it consistent with HTTP REST endpoint path:
|
||||
|
||||
```
|
||||
src/Appwrite/Platform/Modules/[service]/Http/[resource]/[action].php
|
||||
```
|
||||
|
||||
Tips and tricks:
|
||||
|
||||
1. If endpoint doesn't have resource, use service name as resource name too
|
||||
> Example: `Modules/Sites/Http/Sites/Get.php`
|
||||
|
||||
2. If there are multiple resources, use then all in folder structure
|
||||
> Example: `Modules/Sites/Http/Deployments/Builds/Create.php`
|
||||
|
||||
3. Action can only be `Get`, `Create`, `Update`, `Delete` or `XList`
|
||||
|
||||
## Architecture
|
||||
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures.
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures, but our final goal, as we grow, is to be using only microservices.
|
||||
|
||||
---
|
||||
|
||||
@@ -249,17 +188,16 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
|
||||
├── src # Supporting libraries (each lib has one role, common libs are released as individual projects)
|
||||
│ └── Appwrite
|
||||
│ ├── Auth
|
||||
│ ├── Database
|
||||
│ ├── Detector
|
||||
│ ├── Docker
|
||||
| ├── DSN
|
||||
│ ├── Event
|
||||
│ ├── Extend
|
||||
│ ├── GraphQL
|
||||
│ ├── Messaging
|
||||
│ ├── Migration
|
||||
│ ├── Network
|
||||
│ ├── OpenSSL
|
||||
│ ├── Promises
|
||||
│ ├── Realtime
|
||||
│ ├── Resque
|
||||
│ ├── Specification
|
||||
│ ├── Task
|
||||
│ ├── Template
|
||||
@@ -275,13 +213,13 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
|
||||
|
||||
Appwrite's main API container is designed as a monolithic app. This is a decision we made to allow us to develop the project faster while still being a very small team.
|
||||
|
||||
Although the Appwrite API is a monolithic app, it has a very clear separation of concern as each internal service or worker is separated by its container, which allows us to start breaking services for better maintenance and scalability as we grow.
|
||||
Although the Appwrite API is a monolithic app, it has a very clear separation of concern as each internal service or worker is separated by its container, which will allow us as we grow to start breaking services for better maintenance and scalability.
|
||||
|
||||
### The Microservice Part
|
||||
|
||||
Each container in Appwrite is a microservice on its own. Each service is an independent process that can scale without regard to any of the other services.
|
||||
|
||||
Currently, all the Appwrite microservices are intended to communicate using the TCP protocol over a private network. With the exception of the public-facing port 80 and 443, which by default are used to expose the Appwrite HTTP API, you should **avoid exposing any other services' ports**.
|
||||
Currently, all of the Appwrite microservices are intended to communicate using the TCP protocol over a private network. You should be aware to not expose any of the services to the public-facing network, besides the public port 80 and 443, who, by default, are used to expose the Appwrite HTTP API.
|
||||
|
||||
## Ports
|
||||
|
||||
@@ -289,42 +227,43 @@ Appwrite dev version uses ports 80 and 443 as an entry point to the Appwrite API
|
||||
|
||||
## Technology Stack
|
||||
|
||||
To start helping us to improve the Appwrite server by submitting code, prior knowledge of Appwrite's technology stack can help you get started.
|
||||
To start helping us to improve the Appwrite server by submitting code, prior knowledge of Appwrite's technology stack can help you with getting started.
|
||||
|
||||
Appwrite stack is a combination of a variety of open-source technologies and tools. Appwrite backend API is written primarily with PHP version 7 and above, on top of the [Utopia PHP framework](https://github.com/utopia-php/framework). The Appwrite frontend is built with tools like gulp, less, and [litespeed.js](https://github.com/litespeed-js). We use Docker as the container technology to package the Appwrite server for easy on-cloud, on-premise, or on-localhost integration.
|
||||
Appwrite stack is combined from a variety of open-source technologies and tools. Appwrite backend API is written primarily with PHP version 7 and above on top of the [Utopia PHP framework](https://github.com/utopia-php/framework). The Appwrite frontend is built with tools like gulp, less, and [litespeed.js](https://github.com/litespeed-js). We use Docker as the container technology to package the Appwrite server for easy integration on-cloud, on-premise, or on-localhosts.
|
||||
|
||||
### Other Technologies
|
||||
|
||||
- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data).
|
||||
- MariaDB - for database storage and queries.
|
||||
- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data)
|
||||
- MariaDB - for database storage and queries
|
||||
- InfluxDB - for managing stats and time-series based data
|
||||
- Statsd - for sending data over UDP protocol (using Telegraf)
|
||||
- ClamAV - for validating and scanning storage files.
|
||||
- ClamAV - for validating and scanning storage files
|
||||
- Imagemagick - for manipulating and managing image media files.
|
||||
- Webp - for better compression of images on supporting clients.
|
||||
- SMTP - for sending email messages and alerts.
|
||||
- Webp - for better compression of images on supporting clients
|
||||
- SMTP - for sending email messages and alerts
|
||||
- Resque - for managing data queues and scheduled tasks over a Redis server
|
||||
|
||||
## Package Managers
|
||||
|
||||
Appwrite uses a package manager for managing code dependencies for both backend and frontend development. We try our best to avoid creating any unnecessary dependencies. New dependency to the project is subjected to a lead developer's review and approval.
|
||||
Appwrite uses a package manager for managing code dependencies for both backend and frontend development. We try our best to avoid creating any unnecessary, and any new dependency to the project is subjected to a lead developer review and approval.
|
||||
|
||||
Many of Appwrite's internal modules are also used as dependencies to allow other Appwrite projects to reuse them and as a way to contribute back to the community.
|
||||
Many of Appwrite's internal modules are also used as dependencies to allow other Appwrite's projects to reuse them and as a way to contribute them back to the community.
|
||||
|
||||
Appwrite uses [PHP's Composer](https://getcomposer.org/) for managing dependencies on the server-side and [JS NPM](https://www.npmjs.com/) for managing dependencies on the frontend side.
|
||||
|
||||
## Coding Standards
|
||||
|
||||
Appwrite follows the [PHP-FIG standards](https://www.php-fig.org/). Currently, we use both PSR-0 and PSR-12 for coding standards and autoloading standards.
|
||||
Appwrite is following the [PHP-FIG standards](https://www.php-fig.org/). Currently, we are using both PSR-0 and PSR-12 for coding standards and autoloading standards.
|
||||
|
||||
We use prettier for our JS coding standards and auto-formatting for our code.
|
||||
We use prettier for our JS coding standards and auto-formatting our code.
|
||||
|
||||
## Scalability, Speed, and Performance
|
||||
|
||||
Appwrite is built to scale. Please keep in mind that the Appwrite stack can run in different environments and different scales.
|
||||
|
||||
We intend Appwrite to be as easy to set up as possible in a single localhost, and to grow easily into a large environment with dozens and even hundreds of instances.
|
||||
We wish Appwrite will be as easy to set up and in a single, localhost, and easy to grow to a large environment with dozens and even hundreds of instances.
|
||||
|
||||
When contributing code, please take into account the following:
|
||||
When contributing code, please take into account the following considerations:
|
||||
|
||||
- Response Time
|
||||
- Throughput
|
||||
@@ -335,165 +274,25 @@ When contributing code, please take into account the following:
|
||||
- Background Jobs
|
||||
- Task Execution Time
|
||||
|
||||
## Security and Privacy
|
||||
## Security & Privacy
|
||||
|
||||
Security and privacy are extremely important to Appwrite, developers, and users alike. Make sure to follow the best industry standards and practices.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Please avoid introducing new dependencies to Appwrite without consulting the team. New dependencies can be very helpful, but they also introduce new security and privacy risks, add complexity, and impact the total docker image size.
|
||||
Please avoid introducing new dependencies to Appwrite without consulting the team. New dependencies can be very helpful but also introduce new security and privacy issues, complexity, and impact total docker image size.
|
||||
|
||||
Adding a new dependency should have vital value for the product with minimum possible risk.
|
||||
Adding a new dependency should have vital value on the product with minimum possible risk.
|
||||
|
||||
## Introducing New Features
|
||||
|
||||
We would :sparkling_heart: you to contribute to Appwrite, but we also want to ensure Appwrite is loyal to its vision and mission statement :pray:.
|
||||
We would 💖 you to contribute to Appwrite, but we would also like to make sure Appwrite is as great as possible and loyal to its vision and mission statement 🙏.
|
||||
|
||||
For us to find the right balance, please open an issue explaining your ideas before introducing a new pull request.
|
||||
|
||||
This will allow the Appwrite community to sufficiently discuss the new feature value and how it fits within the product roadmap and vision.
|
||||
|
||||
This is also important for the Appwrite lead developers to be able to provide technical input and potentially a different emphasis regarding the feature design and architecture. Some bigger features might need to go through our [RFC process](https://github.com/appwrite/rfc).
|
||||
|
||||
## Adding New Usage Metrics
|
||||
|
||||
These are the current metrics we collect usage stats for:
|
||||
|
||||
| Metric | Description |
|
||||
|--------|-------------------------------------------------|
|
||||
| teams | Total number of teams per project |
|
||||
| users | Total number of users per project|
|
||||
| executions | Total number of executions per project |
|
||||
| databases | Total number of databases per project |
|
||||
| databases.storage | Total amount of storage used by all databases per project (in bytes) |
|
||||
| collections | Total number of collections per project |
|
||||
| {databaseInternalId}.collections | Total number of collections per database|
|
||||
| {databaseInternalId}.storage | Sum of database storage (in bytes) |
|
||||
| documents | Total number of documents per project |
|
||||
| {databaseInternalId}.{collectionInternalId}.documents | Total number of documents per collection |
|
||||
| {databaseInternalId}.{collectionInternalId}.storage | Sum of database storage used by the collection (in bytes) |
|
||||
| buckets | Total number of buckets per project |
|
||||
| files | Total number of files per project |
|
||||
| {bucketInternalId}.files.storage | Sum of files.storage per bucket (in bytes) |
|
||||
| functions | Total number of functions per project |
|
||||
| deployments | Total number of deployments per project |
|
||||
| builds | Total number of builds per project |
|
||||
| {resourceType}.{resourceInternalId}.deployments | Total number of deployments per function |
|
||||
| executions | Total number of executions per project |
|
||||
| {functionInternalId}.executions | Total number of executions per function |
|
||||
| files.storage | Sum of files storage per project (in bytes) |
|
||||
| deployments.storage | Sum of deployments storage per project (in bytes) |
|
||||
| {resourceType}.{resourceInternalId}.deployments.storage | Sum of deployments storage per function (in bytes) |
|
||||
| builds.storage | Sum of builds storage per project (in bytes) |
|
||||
| builds.compute | Sum of compute duration per project (in seconds) |
|
||||
| {functionInternalId}.builds.storage | Sum of builds storage per function (in bytes) |
|
||||
| {functionInternalId}.builds.compute | Sum of compute duration per function (in seconds) |
|
||||
| network.requests | Total number of network requests per project |
|
||||
| executions.compute | Sum of compute duration per project (in seconds) |
|
||||
| network.inbound | Sum of network inbound traffic per project (in bytes)|
|
||||
| network.outbound | Sum of network outbound traffic per project (in bytes)|
|
||||
|
||||
> Note: The curly brackets in the metric name represents a template and is replaced with a value when the metric is processed.
|
||||
|
||||
Metrics are collected within 3 scopes Daily, monthly, an infinity. Adding new usage metric in order to aggregate usage stats is very simple, but very much dependent on where do you want to collect
|
||||
statistics ,via API or via background worker. For both cases you will need to add a `const` variable in `app/init.php` under the usage metrics list using the naming convention `METRIC_<RESOURCE_NAME>` as shown below.
|
||||
|
||||
```php
|
||||
// Usage metrics
|
||||
const METRIC_FUNCTIONS = 'functions';
|
||||
const METRIC_DEPLOYMENTS = 'deployments';
|
||||
const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage';
|
||||
```
|
||||
|
||||
Next follow the appropriate steps below depending on whether you're adding the metric to the API or the worker.
|
||||
|
||||
**API**
|
||||
|
||||
In file `app/controllers/shared/api.php` On the database listener, add to an existing or create a new switch case. Add a call to the usage worker with your new metric const like so:
|
||||
|
||||
```php
|
||||
case $document->getCollection() === 'teams':
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_TEAMS, $value); // per project
|
||||
break;
|
||||
```
|
||||
There are cases when you need to handle metric that has a parent entity, like buckets.
|
||||
Files are linked to a parent bucket, you should verify you remove the files stats when you delete a bucket.
|
||||
|
||||
In that case you need also to handle children removal using addReduce() method call.
|
||||
|
||||
```php
|
||||
|
||||
case $document->getCollection() === 'buckets': //buckets
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_BUCKETS, $value); // per project
|
||||
if ($event === Database::EVENT_DOCUMENT_DELETE) {
|
||||
$queueForStatsUsage
|
||||
->addReduce($document);
|
||||
}
|
||||
break;
|
||||
|
||||
```
|
||||
|
||||
In addition, you will also need to add some logic to the `reduce()` method of the Usage worker located in `/src/Appwrite/Platform/Workers/Usage.php`, like so:
|
||||
|
||||
```php
|
||||
case $document->getCollection() === 'buckets':
|
||||
$files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES)));
|
||||
$storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE)));
|
||||
|
||||
if (!empty($files['value'])) {
|
||||
$metrics[] = [
|
||||
'key' => METRIC_FILES,
|
||||
'value' => ($files['value'] * -1),
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($storage['value'])) {
|
||||
$metrics[] = [
|
||||
'key' => METRIC_FILES_STORAGE,
|
||||
'value' => ($storage['value'] * -1),
|
||||
];
|
||||
}
|
||||
break;
|
||||
```
|
||||
|
||||
**Background worker**
|
||||
|
||||
You need to inject the usage queue in the desired worker on the constructor method
|
||||
```php
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->desc('Functions worker')
|
||||
->groups(['functions'])
|
||||
->inject('message')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('log')
|
||||
->callback(fn (Message $message, Database $dbForProject, Func $queueForFunctions, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log) => $this->action($message, $dbForProject, $queueForFunctions, $queueForEvents, $queueForStatsUsage, $log));
|
||||
}
|
||||
```
|
||||
|
||||
and then trigger the queue with the new metric like so:
|
||||
|
||||
```php
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_BUILDS, 1)
|
||||
->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0))
|
||||
->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000)
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1)
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0))
|
||||
->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000)
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
```
|
||||
This will allow the Appwrite community to have sufficient discussion about the new feature value and how it fits in the product roadmap and vision.
|
||||
|
||||
This is also important for the Appwrite lead developers to be able to give technical input and different emphasis regarding the feature design and architecture. Some bigger features might need to go through our [RFC process](https://github.com/appwrite/rfc).
|
||||
|
||||
## Build
|
||||
|
||||
@@ -517,46 +316,30 @@ The Runtimes for all supported cloud functions (multicore builds) can be found a
|
||||
|
||||
## Generate SDK
|
||||
|
||||
The following steps are used to generate a new console SDK:
|
||||
For generating a new console SDK follow the next steps:
|
||||
|
||||
1. Update the console spec file located at `app/config/specs/swagger2-<version-number>.console.json` using Appwrite Tasks. Run the `php app/cli.php specs version=<version-number> mode=normal` command in a running `appwrite/appwrite` container.
|
||||
2. Generate a new SDK using the command `php app/cli.php sdks`.
|
||||
3. Change your working dir using `cd app/sdks/console-web`.
|
||||
4. Build the new SDK `npm run build`.
|
||||
5. Copy `iife/sdk.js` to `appwrite.js`.
|
||||
6. Go back to the root of the project `run npm run build`.
|
||||
1. Update the console spec file located at `app/config/specs/swagger2-<version-number>.console.json` using Appwrite Tasks. Run the `php app/cli.php specs <version-number> normal` command in a running `appwrite/appwrite` container.
|
||||
2. Generate a new SDK using the command `php app/cli.php sdks`
|
||||
3. Change your working dir using `cd app/sdks/console-web`
|
||||
4. Build the new SDK `npm run build`
|
||||
5. Copy `iife/sdk.js` to `appwrite.js`
|
||||
6. Go back to the root of the project `run npm run build`
|
||||
|
||||
## Checklist for Releasing SDKs
|
||||
|
||||
Things to remember when releasing SDKs:
|
||||
Things to remember when releasing SDKs
|
||||
|
||||
- Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these).
|
||||
- Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs are in there.
|
||||
- Update SDK versions as required on **app/config/platforms.php**.
|
||||
- Generate SDKs using the command `php app/cli.php sdks` and follow the instructions.
|
||||
- Release new tags on GitHub repository for each SDK.
|
||||
- Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these)
|
||||
- Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs in there
|
||||
- Update SDK versions as required on **app/config/platforms.php**
|
||||
- Generate SDKs using the command `php app/cli.php sdks` and follow the instructions
|
||||
- Release new tags on GitHub repository for each SDKs
|
||||
|
||||
## Debug
|
||||
|
||||
Appwrite uses [XDebug](https://github.com/xdebug/xdebug) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
|
||||
Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection.
|
||||
|
||||
If you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection:
|
||||
|
||||
1. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
2. If needed edit the **dev/xdebug.ini** file to your needs.
|
||||
3. Launch your Appwrite instance while your debugger is listening for connections.
|
||||
|
||||
## Profiling
|
||||
Appwrite uses XDebug [Profiler](https://xdebug.org/docs/profiler) for generating **CacheGrind** files. The generated file would be located in each of the `appwrite` containers inside the `/tmp/xdebug` folder.
|
||||
|
||||
To disable the profiler while debugging remove the `,profiler` mode from the `xdebug.ini` file
|
||||
```diff
|
||||
zend_extension=xdebug
|
||||
|
||||
[xdebug]
|
||||
-xdebug.mode=develop,debug,profile
|
||||
+xdebug.mode=develop,debug
|
||||
```
|
||||
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger won't connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
|
||||
### VS Code Launch Configuration
|
||||
|
||||
@@ -574,7 +357,7 @@ zend_extension=xdebug
|
||||
|
||||
### PHPStorm Setup
|
||||
|
||||
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, under **Xdebug** set the debug port to **9005** and enable the **can accept external connections** checkbox.
|
||||
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, there under **Xdebug** set the debug port to **9005** and enable **can accept external connections** checkbox.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -602,12 +385,6 @@ To run end-2-end tests for a specific service use:
|
||||
docker compose exec appwrite test /usr/src/code/tests/e2e/Services/[ServiceName]
|
||||
```
|
||||
|
||||
To run one specific test:
|
||||
|
||||
```bash
|
||||
docker compose exec appwrite vendor/bin/phpunit --filter [FunctionName]
|
||||
```
|
||||
|
||||
## Benchmarking
|
||||
|
||||
You can use WRK Docker image to benchmark the server performance. Benchmarking is extremely useful when you want to compare how the server behaves before and after a change has been applied. Replace [APPWRITE_HOSTNAME_OR_IP] with your Appwrite server hostname or IP. Note that localhost is not accessible from inside the WRK container.
|
||||
@@ -651,59 +428,39 @@ composer lint
|
||||
composer lint <your file path>
|
||||
```
|
||||
|
||||
## Clearing the Cache
|
||||
|
||||
If you need to clear the cache, you can do so by running the following command:
|
||||
|
||||
```bash
|
||||
docker compose exec redis redis-cli FLUSHALL
|
||||
```
|
||||
|
||||
## Using preview domains locally
|
||||
|
||||
Appwrite Functions are automatically given a domain you can visit to execute the function. This domain has format `[SOMETHING].functions.localhost` unless you changed `_APP_DOMAIN_FUNCTIONS` environment variable. This default value works great when running Appwrite locally, but it can be impossible to use preview domains with Cloud woekspaces such as Gitpod or GitHub Codespaces.
|
||||
|
||||
To use preview domains on Cloud workspaces, you can visit hostname provided by them, and supply function's preview domain as URL parameter:
|
||||
|
||||
```
|
||||
https://8080-appwrite-appwrite-mjeb3ebilwv.ws-eu116.gitpod.io/ping?preview=672b3c7eab1ac523ccf5.functions.localhost
|
||||
```
|
||||
|
||||
The path was set to `/ping` intentionally. Visiting `/` for preview domains might trigger Console background worker, and trigger redirect to Console without our preview URL param. Visiting different path ensures this doesnt happen.
|
||||
|
||||
## Tutorials
|
||||
|
||||
From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:
|
||||
|
||||
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
||||
- [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
|
||||
- [Running in Production](https://appwrite.io/docs/advanced/self-hosting/production)
|
||||
- [Appwrite Environment Variables](./docs/tutorials/environment-variables.md)
|
||||
- [Running in Production](./docs/tutorials/running-in-production.md)
|
||||
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
||||
|
||||
## Other Ways to Help
|
||||
|
||||
Pull requests are great, but there are many other ways you can help Appwrite.
|
||||
Pull requests are great, but there are many other areas where you can help Appwrite.
|
||||
|
||||
### Blogging & Speaking
|
||||
|
||||
Blogging, speaking about, or creating tutorials about one of Appwrite’s many features are great ways to get the word out about Appwrite. Mention [@appwrite on Twitter](https://twitter.com/appwrite) and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
|
||||
Blogging, speaking about, or creating tutorials about one of Appwrite’s many features. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
|
||||
|
||||
### Presenting at Meetups
|
||||
|
||||
We encourage our contributors to present at meetups and conferences about your Appwrite projects. Your unique challenges and successes in building things with Appwrite can provide great speaking material. We’d love to review your talk abstract/CFP, so get in touch with us if you’d like some help!
|
||||
Presenting at meetups and conferences about your Appwrite projects. Your unique challenges and successes in building things with Appwrite can provide great speaking material. We’d love to review your talk abstract/CFP, so get in touch with us if you’d like some help!
|
||||
|
||||
### Sending Feedbacks and Reporting Bugs
|
||||
### Sending Feedbacks & Reporting Bugs
|
||||
|
||||
Sending feedback is a great way for us to understand your different use cases of Appwrite better. If you had any issues, bugs, or want to share your experience, feel free to do so on our GitHub issues page or at our [Discord channel](https://discord.gg/GSeTUeA).
|
||||
Sending feedback is a great way for us to understand your different use cases of Appwrite better. If you had any issues, bugs, or want to share about your experience, feel free to do so on our GitHub issues page or at our [Discord channel](https://discord.gg/GSeTUeA).
|
||||
|
||||
### Submitting New Ideas
|
||||
|
||||
If you think Appwrite could use a new feature, please open an issue on our GitHub repository, stating as much information as you have about your new idea and its implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.
|
||||
If you think Appwrite could use a new feature, please open an issue on our GitHub repository, stating as much information as you can think about your new idea and it's implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.
|
||||
|
||||
### Improving Documentation
|
||||
|
||||
Submitting documentation updates, enhancements, designs, or bug fixes, as well as spelling or grammar fixes is much appreciated.
|
||||
Submitting documentation updates, enhancements, designs, or bug fixes. Spelling or grammar fixes will be very much appreciated.
|
||||
|
||||
### Helping Someone
|
||||
|
||||
Consider searching for Appwrite on Discord, GitHub, or StackOverflow to help someone who needs help. You can also help by teaching others how to contribute to Appwrite's repo!
|
||||
Searching for Appwrite on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to Appwrite's repo!
|
||||
|
||||
+318
-59
@@ -1,4 +1,4 @@
|
||||
FROM composer:2 AS composer
|
||||
FROM composer:2.0 as composer
|
||||
|
||||
ARG TESTING=false
|
||||
ENV TESTING=$TESTING
|
||||
@@ -12,7 +12,157 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
|
||||
--no-plugins --no-scripts --prefer-dist \
|
||||
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
|
||||
|
||||
FROM appwrite/base:1.0.0 AS base
|
||||
FROM node:16.14.2-alpine3.15 as node
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
COPY package-lock.json /usr/local/src/
|
||||
COPY package.json /usr/local/src/
|
||||
COPY gulpfile.js /usr/local/src/
|
||||
COPY public /usr/local/src/public
|
||||
|
||||
RUN npm ci
|
||||
RUN npm run build
|
||||
|
||||
FROM php:8.0.18-cli-alpine3.15 as compile
|
||||
|
||||
ARG DEBUG=false
|
||||
ENV DEBUG=$DEBUG
|
||||
|
||||
ENV PHP_REDIS_VERSION=5.3.7 \
|
||||
PHP_MONGODB_VERSION=1.13.0 \
|
||||
PHP_SWOOLE_VERSION=v4.8.10 \
|
||||
PHP_IMAGICK_VERSION=3.7.0 \
|
||||
PHP_YAML_VERSION=2.2.2 \
|
||||
PHP_MAXMINDDB_VERSION=v1.11.0 \
|
||||
PHP_ZSTD_VERSION="4504e4186e79b197cfcb75d4d09aa47ef7d92fe9 "
|
||||
|
||||
RUN \
|
||||
apk add --no-cache --virtual .deps \
|
||||
make \
|
||||
automake \
|
||||
autoconf \
|
||||
gcc \
|
||||
g++ \
|
||||
git \
|
||||
zlib-dev \
|
||||
brotli-dev \
|
||||
openssl-dev \
|
||||
yaml-dev \
|
||||
imagemagick \
|
||||
imagemagick-dev \
|
||||
libmaxminddb-dev \
|
||||
zstd-dev
|
||||
|
||||
RUN docker-php-ext-install sockets
|
||||
|
||||
FROM compile AS redis
|
||||
RUN \
|
||||
# Redis Extension
|
||||
git clone --depth 1 --branch $PHP_REDIS_VERSION https://github.com/phpredis/phpredis.git && \
|
||||
cd phpredis && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install
|
||||
|
||||
## Swoole Extension
|
||||
FROM compile AS swoole
|
||||
RUN \
|
||||
git clone --depth 1 --branch $PHP_SWOOLE_VERSION https://github.com/swoole/swoole-src.git && \
|
||||
cd swoole-src && \
|
||||
phpize && \
|
||||
./configure --enable-sockets --enable-http2 --enable-openssl && \
|
||||
make && make install && \
|
||||
cd ..
|
||||
|
||||
## Swoole Debugger setup
|
||||
RUN if [ "$DEBUG" == "true" ]; then \
|
||||
cd /tmp && \
|
||||
apk add boost-dev && \
|
||||
git clone --depth 1 https://github.com/swoole/yasd && \
|
||||
cd yasd && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install && \
|
||||
cd ..;\
|
||||
fi
|
||||
|
||||
## Imagick Extension
|
||||
FROM compile AS imagick
|
||||
RUN \
|
||||
git clone --depth 1 --branch $PHP_IMAGICK_VERSION https://github.com/imagick/imagick && \
|
||||
cd imagick && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install
|
||||
|
||||
## YAML Extension
|
||||
FROM compile AS yaml
|
||||
RUN \
|
||||
git clone --depth 1 --branch $PHP_YAML_VERSION https://github.com/php/pecl-file_formats-yaml && \
|
||||
cd pecl-file_formats-yaml && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install
|
||||
|
||||
## Maxminddb extension
|
||||
FROM compile AS maxmind
|
||||
RUN \
|
||||
git clone --depth 1 --branch $PHP_MAXMINDDB_VERSION https://github.com/maxmind/MaxMind-DB-Reader-php.git && \
|
||||
cd MaxMind-DB-Reader-php && \
|
||||
cd ext && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install
|
||||
|
||||
# Mongodb Extension
|
||||
FROM compile as mongodb
|
||||
RUN \
|
||||
git clone --depth 1 --branch $PHP_MONGODB_VERSION https://github.com/mongodb/mongo-php-driver.git && \
|
||||
cd mongo-php-driver && \
|
||||
git submodule update --init && \
|
||||
phpize && \
|
||||
./configure && \
|
||||
make && make install
|
||||
|
||||
# Zstd Compression
|
||||
FROM compile as zstd
|
||||
RUN git clone --recursive -n https://github.com/kjdev/php-ext-zstd.git \
|
||||
&& cd php-ext-zstd \
|
||||
&& git checkout $PHP_ZSTD_VERSION \
|
||||
&& phpize \
|
||||
&& ./configure --with-libzstd \
|
||||
&& make && make install
|
||||
|
||||
|
||||
# Rust Extensions Compile Image
|
||||
FROM php:8.0.18-cli as rust_compile
|
||||
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
|
||||
ENV PATH=/root/.cargo/bin:$PATH
|
||||
|
||||
RUN apt-get update && apt-get install musl-tools build-essential clang-11 git -y
|
||||
RUN rustup target add $(uname -m)-unknown-linux-musl
|
||||
|
||||
# Install ZigBuild for easier cross-compilation
|
||||
RUN curl https://ziglang.org/builds/zig-linux-$(uname -m)-0.10.0-dev.2674+d980c6a38.tar.xz --output /tmp/zig.tar.xz
|
||||
RUN tar -xf /tmp/zig.tar.xz -C /tmp/ && cp -r /tmp/zig-linux-$(uname -m)-0.10.0-dev.2674+d980c6a38 /tmp/zig/
|
||||
ENV PATH=/tmp/zig:$PATH
|
||||
RUN cargo install cargo-zigbuild
|
||||
ENV RUSTFLAGS="-C target-feature=-crt-static"
|
||||
|
||||
FROM rust_compile as scrypt
|
||||
|
||||
WORKDIR /usr/local/lib/php/extensions/
|
||||
|
||||
RUN \
|
||||
git clone --depth 1 https://github.com/appwrite/php-scrypt.git && \
|
||||
cd php-scrypt && \
|
||||
cargo zigbuild --workspace --all-targets --target $(uname -m)-unknown-linux-musl --release && \
|
||||
mv target/$(uname -m)-unknown-linux-musl/release/libphp_scrypt.so target/libphp_scrypt.so
|
||||
|
||||
FROM php:8.0.18-cli-alpine3.15 as final
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
@@ -20,105 +170,214 @@ ARG VERSION=dev
|
||||
ARG DEBUG=false
|
||||
ENV DEBUG=$DEBUG
|
||||
|
||||
ENV _APP_VERSION=$VERSION \
|
||||
_APP_HOME=https://appwrite.io
|
||||
ENV DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
|
||||
ENV DOCKER_COMPOSE_VERSION=v2.5.0
|
||||
|
||||
ENV _APP_SERVER=swoole \
|
||||
_APP_ENV=production \
|
||||
_APP_LOCALE=en \
|
||||
_APP_WORKER_PER_CORE= \
|
||||
_APP_DOMAIN=localhost \
|
||||
_APP_DOMAIN_TARGET=localhost \
|
||||
_APP_HOME=https://appwrite.io \
|
||||
_APP_EDITION=community \
|
||||
_APP_CONSOLE_WHITELIST_ROOT=enabled \
|
||||
_APP_CONSOLE_WHITELIST_EMAILS= \
|
||||
_APP_CONSOLE_WHITELIST_IPS= \
|
||||
_APP_SYSTEM_EMAIL_NAME= \
|
||||
_APP_SYSTEM_EMAIL_ADDRESS= \
|
||||
_APP_SYSTEM_RESPONSE_FORMAT= \
|
||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS= \
|
||||
_APP_OPTIONS_ABUSE=enabled \
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled \
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key \
|
||||
_APP_STORAGE_LIMIT=10000000 \
|
||||
_APP_STORAGE_ANTIVIRUS=enabled \
|
||||
_APP_STORAGE_ANTIVIRUS_HOST=clamav \
|
||||
_APP_STORAGE_ANTIVIRUS_PORT=3310 \
|
||||
_APP_STORAGE_DEVICE=Local \
|
||||
_APP_STORAGE_S3_ACCESS_KEY= \
|
||||
_APP_STORAGE_S3_SECRET= \
|
||||
_APP_STORAGE_S3_REGION= \
|
||||
_APP_STORAGE_S3_BUCKET= \
|
||||
_APP_STORAGE_DO_SPACES_ACCESS_KEY= \
|
||||
_APP_STORAGE_DO_SPACES_SECRET= \
|
||||
_APP_STORAGE_DO_SPACES_REGION= \
|
||||
_APP_STORAGE_DO_SPACES_BUCKET= \
|
||||
_APP_STORAGE_BACKBLAZE_ACCESS_KEY= \
|
||||
_APP_STORAGE_BACKBLAZE_SECRET= \
|
||||
_APP_STORAGE_BACKBLAZE_REGION= \
|
||||
_APP_STORAGE_BACKBLAZE_BUCKET= \
|
||||
_APP_STORAGE_LINODE_ACCESS_KEY= \
|
||||
_APP_STORAGE_LINODE_SECRET= \
|
||||
_APP_STORAGE_LINODE_REGION= \
|
||||
_APP_STORAGE_LINODE_BUCKET= \
|
||||
_APP_STORAGE_WASABI_ACCESS_KEY= \
|
||||
_APP_STORAGE_WASABI_SECRET= \
|
||||
_APP_STORAGE_WASABI_REGION= \
|
||||
_APP_STORAGE_WASABI_BUCKET= \
|
||||
_APP_REDIS_HOST=redis \
|
||||
_APP_REDIS_PORT=6379 \
|
||||
_APP_DB_HOST=mariadb \
|
||||
_APP_DB_PORT=3306 \
|
||||
_APP_DB_USER=root \
|
||||
_APP_DB_PASS=password \
|
||||
_APP_DB_SCHEMA=appwrite \
|
||||
_APP_INFLUXDB_HOST=influxdb \
|
||||
_APP_INFLUXDB_PORT=8086 \
|
||||
_APP_STATSD_HOST=telegraf \
|
||||
_APP_STATSD_PORT=8125 \
|
||||
_APP_SMTP_HOST= \
|
||||
_APP_SMTP_PORT= \
|
||||
_APP_SMTP_SECURE= \
|
||||
_APP_SMTP_USERNAME= \
|
||||
_APP_SMTP_PASSWORD= \
|
||||
_APP_SMS_PROVIDER= \
|
||||
_APP_SMS_FROM= \
|
||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000 \
|
||||
_APP_FUNCTIONS_TIMEOUT=900 \
|
||||
_APP_FUNCTIONS_CONTAINERS=10 \
|
||||
_APP_FUNCTIONS_CPUS=1 \
|
||||
_APP_FUNCTIONS_MEMORY=128 \
|
||||
_APP_FUNCTIONS_MEMORY_SWAP=128 \
|
||||
_APP_EXECUTOR_SECRET=a-random-secret \
|
||||
_APP_FUNCTIONS_PROXY_SECRET=a-random-secret \
|
||||
_APP_FUNCTIONS_PROXY_HOST=http://appwrite-functions-proxy/v1 \
|
||||
_APP_EXECUTORS=exc1 \
|
||||
_APP_FUNCTIONS_PROXY_ADAPTER=round-robin \
|
||||
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes \
|
||||
_APP_SETUP=self-hosted \
|
||||
_APP_VERSION=$VERSION \
|
||||
_APP_USAGE_STATS=enabled \
|
||||
_APP_USAGE_TIMESERIES_INTERVAL=30 \
|
||||
_APP_USAGE_DATABASE_INTERVAL=900 \
|
||||
# 14 Days = 1209600 s
|
||||
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600 \
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT=1209600 \
|
||||
# 1 Day = 86400 s
|
||||
_APP_MAINTENANCE_RETENTION_ABUSE=86400 \
|
||||
_APP_MAINTENANCE_INTERVAL=86400 \
|
||||
_APP_LOGGING_PROVIDER= \
|
||||
_APP_LOGGING_CONFIG=
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN \
|
||||
if [ "$DEBUG" == "true" ]; then \
|
||||
apk update \
|
||||
&& apk add --no-cache --virtual .deps \
|
||||
make \
|
||||
automake \
|
||||
autoconf \
|
||||
gcc \
|
||||
g++ \
|
||||
curl-dev \
|
||||
&& apk add --no-cache \
|
||||
libstdc++ \
|
||||
certbot \
|
||||
brotli-dev \
|
||||
yaml-dev \
|
||||
imagemagick \
|
||||
imagemagick-dev \
|
||||
libmaxminddb-dev \
|
||||
certbot \
|
||||
docker-cli \
|
||||
libgomp \
|
||||
&& docker-php-ext-install sockets opcache pdo_mysql \
|
||||
&& apk del .deps \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN \
|
||||
mkdir -p $DOCKER_CONFIG/cli-plugins \
|
||||
&& ARCH=$(uname -m) && if [ $ARCH == "armv7l" ]; then ARCH="armv7"; fi \
|
||||
&& curl -SL https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-linux-$ARCH -o $DOCKER_CONFIG/cli-plugins/docker-compose \
|
||||
&& chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
|
||||
RUN \
|
||||
if [ "$DEBUG" == "true" ]; then \
|
||||
apk add boost boost-dev; \
|
||||
fi
|
||||
fi
|
||||
|
||||
WORKDIR /usr/src/code
|
||||
|
||||
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
|
||||
COPY --from=node /usr/local/src/public/dist /usr/src/code/public/dist
|
||||
COPY --from=swoole /usr/local/lib/php/extensions/no-debug-non-zts-20200930/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yasd.so* /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=redis /usr/local/lib/php/extensions/no-debug-non-zts-20200930/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=imagick /usr/local/lib/php/extensions/no-debug-non-zts-20200930/imagick.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=yaml /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=maxmind /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20200930/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=scrypt /usr/local/lib/php/extensions/php-scrypt/target/libphp_scrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
COPY --from=zstd /usr/local/lib/php/extensions/no-debug-non-zts-20200930/zstd.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
|
||||
|
||||
# Add Source Code
|
||||
COPY ./app /usr/src/code/app
|
||||
COPY ./public /usr/src/code/public
|
||||
COPY ./bin /usr/local/bin
|
||||
COPY ./docs /usr/src/code/docs
|
||||
COPY ./public/fonts /usr/src/code/public/fonts
|
||||
COPY ./public/images /usr/src/code/public/images
|
||||
COPY ./src /usr/src/code/src
|
||||
COPY ./dev /usr/src/code/dev
|
||||
COPY ./mongo-init.js /usr/src/code/mongo-init.js
|
||||
COPY ./mongo-entrypoint.sh /usr/src/code/mongo-entrypoint.sh
|
||||
|
||||
# Set Volumes
|
||||
RUN mkdir -p /storage/uploads && \
|
||||
mkdir -p /storage/imports && \
|
||||
mkdir -p /storage/cache && \
|
||||
mkdir -p /storage/config && \
|
||||
mkdir -p /storage/certificates && \
|
||||
mkdir -p /storage/functions && \
|
||||
mkdir -p /storage/debug && \
|
||||
chown -Rf www-data:www-data /storage/uploads && chmod -Rf 0755 /storage/uploads && \
|
||||
chown -Rf www-data:www-data /storage/imports && chmod -Rf 0755 /storage/imports && \
|
||||
chown -Rf www-data:www-data /storage/cache && chmod -Rf 0755 /storage/cache && \
|
||||
chown -Rf www-data:www-data /storage/config && chmod -Rf 0755 /storage/config && \
|
||||
chown -Rf www-data:www-data /storage/certificates && chmod -Rf 0755 /storage/certificates && \
|
||||
chown -Rf www-data:www-data /storage/functions && chmod -Rf 0755 /storage/functions && \
|
||||
chown -Rf www-data:www-data /storage/debug && chmod -Rf 0755 /storage/debug
|
||||
chown -Rf www-data.www-data /storage/uploads && chmod -Rf 0755 /storage/uploads && \
|
||||
chown -Rf www-data.www-data /storage/cache && chmod -Rf 0755 /storage/cache && \
|
||||
chown -Rf www-data.www-data /storage/config && chmod -Rf 0755 /storage/config && \
|
||||
chown -Rf www-data.www-data /storage/certificates && chmod -Rf 0755 /storage/certificates && \
|
||||
chown -Rf www-data.www-data /storage/functions && chmod -Rf 0755 /storage/functions && \
|
||||
chown -Rf www-data.www-data /storage/debug && chmod -Rf 0755 /storage/debug
|
||||
|
||||
# Executables
|
||||
RUN chmod +x /usr/local/bin/doctor && \
|
||||
chmod +x /usr/local/bin/maintenance && \
|
||||
chmod +x /usr/local/bin/usage && \
|
||||
chmod +x /usr/local/bin/install && \
|
||||
chmod +x /usr/local/bin/interval && \
|
||||
chmod +x /usr/local/bin/maintenance && \
|
||||
chmod +x /usr/local/bin/migrate && \
|
||||
chmod +x /usr/local/bin/realtime && \
|
||||
chmod +x /usr/local/bin/schedule-functions && \
|
||||
chmod +x /usr/local/bin/schedule-executions && \
|
||||
chmod +x /usr/local/bin/schedule-messages && \
|
||||
chmod +x /usr/local/bin/executor && \
|
||||
chmod +x /usr/local/bin/functions-proxy && \
|
||||
chmod +x /usr/local/bin/schedule && \
|
||||
chmod +x /usr/local/bin/sdks && \
|
||||
chmod +x /usr/local/bin/specs && \
|
||||
chmod +x /usr/local/bin/ssl && \
|
||||
chmod +x /usr/local/bin/screenshot && \
|
||||
chmod +x /usr/local/bin/test && \
|
||||
chmod +x /usr/local/bin/upgrade && \
|
||||
chmod +x /usr/local/bin/vars && \
|
||||
chmod +x /usr/local/bin/queue-retry && \
|
||||
chmod +x /usr/local/bin/queue-count-failed && \
|
||||
chmod +x /usr/local/bin/queue-count-processing && \
|
||||
chmod +x /usr/local/bin/queue-count-success && \
|
||||
chmod +x /usr/local/bin/worker-audits && \
|
||||
chmod +x /usr/local/bin/worker-builds && \
|
||||
chmod +x /usr/local/bin/worker-screenshots && \
|
||||
chmod +x /usr/local/bin/worker-certificates && \
|
||||
chmod +x /usr/local/bin/worker-databases && \
|
||||
chmod +x /usr/local/bin/worker-deletes && \
|
||||
chmod +x /usr/local/bin/worker-executions && \
|
||||
chmod +x /usr/local/bin/worker-functions && \
|
||||
chmod +x /usr/local/bin/worker-builds && \
|
||||
chmod +x /usr/local/bin/worker-mails && \
|
||||
chmod +x /usr/local/bin/worker-messaging && \
|
||||
chmod +x /usr/local/bin/worker-migrations && \
|
||||
chmod +x /usr/local/bin/worker-webhooks && \
|
||||
chmod +x /usr/local/bin/worker-stats-usage && \
|
||||
chmod +x /usr/local/bin/stats-resources && \
|
||||
chmod +x /usr/local/bin/worker-stats-resources
|
||||
chmod +x /usr/local/bin/worker-webhooks
|
||||
|
||||
# Letsencrypt Permissions
|
||||
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
||||
|
||||
FROM base AS production
|
||||
# Enable Extensions
|
||||
RUN echo extension=swoole.so >> /usr/local/etc/php/conf.d/swoole.ini
|
||||
RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini
|
||||
RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini
|
||||
RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini
|
||||
RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini
|
||||
RUN echo extension=libphp_scrypt.so >> /usr/local/etc/php/conf.d/libphp_scrypt.ini
|
||||
RUN echo extension=zstd.so >> /usr/local/etc/php/conf.d/zstd.ini
|
||||
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
||||
|
||||
RUN rm -rf /usr/src/code/app/config/specs && \
|
||||
rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20240924/xdebug.so && \
|
||||
find /usr -name '*.a' -delete 2>/dev/null || true && \
|
||||
find /usr -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true && \
|
||||
find /usr -name '*.pyc' -delete 2>/dev/null || true
|
||||
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
||||
RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "default_socket_timeout=-1" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.jit_buffer_size=100M" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.jit=1235" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD [ "php", "app/http.php" ]
|
||||
|
||||
FROM base AS development
|
||||
|
||||
COPY ./docs /usr/src/code/docs
|
||||
COPY ./dev /usr/src/code/dev
|
||||
|
||||
RUN if [ "$DEBUG" = "true" ]; then \
|
||||
cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini && \
|
||||
mkdir -p /tmp/xdebug && \
|
||||
apk add --update --no-cache openssh-client github-cli; \
|
||||
fi
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD [ "php", "app/http.php" ]
|
||||
CMD [ "php", "app/http.php", "-dopcache.preload=opcache.preload=/usr/src/code/app/preload.php" ]
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# Appwrite hacktoberfest contribution
|
||||
|
||||
Welcome to the Appwrite Hacktoberfest contribution! We appreciate your interest in contributing to our open-source project. Please read this carefully to understand how to get started and make your contributions count.
|
||||
|
||||
## Familiarize with the project
|
||||
|
||||
Before you start contributing, familiarize yourself with our project by reading the [main README](https://github.com/appwrite/appwrite/blob/main/README.md).
|
||||
|
||||
## Code of conduct
|
||||
|
||||
Please ensure that you always follow our [Code of Conduct](https://github.com/appwrite/awesome-appwrite/blob/master/CODE_OF_CONDUCT.md). We aim to maintain a respectful and inclusive community.
|
||||
|
||||
## Contributing guide
|
||||
|
||||
Please review our [Contributing Guide](https://github.com/appwrite/appwrite/blob/main/CONTRIBUTING.md) before contributing. It will help you learn about the architecture, instructions on how to update code, run tests, and submit a PR.
|
||||
|
||||
## Hacktoberfest contribution guidelines
|
||||
|
||||
To participate in Hacktoberfest with Appwrite, follow these guidelines:
|
||||
|
||||
1. **Valid issues**: To make your contribution count, please look for issues labeled with `hacktoberfest`. Only issues labeled with `hacktoberfest` will count as a valid contribution.
|
||||
|
||||
2. **Wait for issue assignment**: After you have identified an issue to work on, please wait for it to be assigned to you by our team. We assign issues on a first-come, first-serve basis.
|
||||
|
||||
3. **Knowing about labels**: We do not have the `hacktoberfest` label in our repositories, but we use it on specific issues. For your pull request to be valid, our team will review and add the `hacktoberfest-accepted` label once it meets the criteria.
|
||||
|
||||
4. **Discuss new issues**: If you're interested in finding and adding new issues for Hacktoberfest, please discuss it with the team on our [Discord server](https://appwrite.io/discord) in the `#hacktoberfest` channel.
|
||||
|
||||
5. **Be patient with pull request reviews**: PR reviews may take up to 15 days due to the volume of contributions. However, we also host PR review parties every week where you can add your PRs for instant review.
|
||||
|
||||
6. **Regular updates**: If you've been assigned an issue, it's essential to share updates every 3 days. Failure to do so may result in being unassigned from the issue.
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Fork the Appwrite repository you'd like to contribute to.
|
||||
|
||||
2. Clone your forked repository to your local machine.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/repository-name.git
|
||||
```
|
||||
|
||||
3. Create a new branch for your contribution.
|
||||
|
||||
```bash
|
||||
git checkout -b TYPE-ISSUE_ID-DESCRIPTION
|
||||
```
|
||||
4. Make your changes, commit them, and push them to your forked repository.
|
||||
|
||||
```bash
|
||||
git commit -m "Add your commit message here"
|
||||
git push origin TYPE-ISSUE_ID-DESCRIPTION
|
||||
```
|
||||
|
||||
5. Create a Pull Request (PR) from your forked repository to the Appwrite repository. Be sure to reference the issue you are addressing in your PR description.
|
||||
|
||||
Thank you for contributing to Appwrite, and we look forward to your Hacktoberfest contributions! If you have any questions or need assistance, feel free to ask on our Discord server or in the issue discussion. Happy hacking!
|
||||
+49
-109
@@ -1,8 +1,6 @@
|
||||
> 好消息!Appwrite 云现已进入公开测试版!立即访问 cloud.appwrite.io 注册,体验无忧的托管服务。今天就加入我们的云端吧!:cloud: :tada:
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://appwrite.io" target="_blank"><img src="./public/images/banner.png" alt="Appwrite banner, with logo and text saying "The Developer's Cloud""></a>
|
||||
<a href="https://appwrite.io" target="_blank"><img width="260" height="39" src="https://appwrite.io/images/appwrite.svg" alt="Appwrite Logo"></a>
|
||||
<br />
|
||||
<br />
|
||||
<b>适用于[Flutter/Vue/Angular/React/iOS/Android/* 等等平台 *]的完整后端服务</b>
|
||||
@@ -12,10 +10,9 @@
|
||||
|
||||
<!-- [](https://travis-ci.com/appwrite/appwrite) -->
|
||||
|
||||
[](https://appwrite.io/company/careers)
|
||||
[](https://hacktoberfest.appwrite.io)
|
||||
[](https://appwrite.io/discord?r=Github)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://twitter.com/appwrite)
|
||||
|
||||
<!-- [](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||
@@ -24,9 +21,7 @@
|
||||
|
||||
[English](README.md) | 简体中文
|
||||
|
||||
[**Appwrite 云公开测试版!立即注册!**](https://cloud.appwrite.io)
|
||||
|
||||
Appwrite 是一个基于 Docker 的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,原生应用,以及后端。它既包含后端服务器,也提供了用于部署静态和服务器端渲染前端的完全集成托管解决方案。Appwrite 通过视觉化界面简化了从零开始构建现代应用的复杂性和重复性,让您能够更快地构建安全的全栈应用。
|
||||
Appwrite是一个基于Docker的端到端开发者平台,其容器化的微服务库可应用于网页端,移动端,以及后端。Appwrite 通过视觉化界面极简了从零编写 API 的繁琐过程,在保证软件安全的前提下为开发者创造了一个高效的开发环境。
|
||||
|
||||
Appwrite 可以提供给开发者用户验证,外部授权,用户数据读写检索,文件储存,图像处理,云函数计算,[等多种服务](https://appwrite.io/docs).
|
||||
|
||||
@@ -36,7 +31,6 @@ Appwrite 可以提供给开发者用户验证,外部授权,用户数据读
|
||||
|
||||
内容:
|
||||
|
||||
- [开始](#开始)
|
||||
- [安装](#安装)
|
||||
- [Unix](#unix)
|
||||
- [Windows](#windows)
|
||||
@@ -55,15 +49,11 @@ Appwrite 可以提供给开发者用户验证,外部授权,用户数据读
|
||||
- [订阅我们](#订阅我们)
|
||||
- [版权说明](#版权说明)
|
||||
|
||||
## 开始
|
||||
|
||||
要轻松开始使用 Appwrite,您可以[**免费注册 Appwrite Cloud**](https://cloud.appwrite.io/)。在 Appwrite Cloud 公开测试版期间,您可以完全免费使用 Appwrite,而且我们不会收集您的信用卡信息。
|
||||
|
||||
## 安装
|
||||
|
||||
Appwrite 的容器化服务器只需要一行指令就可以运行。您可以使用 docker-compose 在本地主机上运行 Appwrite,也可以在任何其他容器化工具(如 [Kubernetes](https://kubernetes.io/docs/home/)、[Docker Swarm](https://docs.docker.com/engine/swarm/) 或 [Rancher](https://rancher.com/docs/))上运行 Appwrite。
|
||||
Appwrite 的容器化服务器只需要一行指令就可以运行。您可以使用 docker-compose 在本地主机上运行 Appwrite,也可以在任何其他容器化工具(如 Kubernetes、Docker Swarm 或 Rancher)上运行 Appwrite。
|
||||
|
||||
启动 Appwrite 服务器的最简单方法是运行我们的 docker-compose 文件。在运行安装命令之前,请确保您的机器上安装了 [Docker](https://dockerdocs.cn/get-docker/index.html):
|
||||
开始运行 Appwrite 服务器的最简单方法是运行我们的 docker-compose 文件。在运行安装命令之前,请确保您的机器上安装了 [Docker](https://dockerdocs.cn/get-docker/index.html):
|
||||
|
||||
### Unix
|
||||
|
||||
@@ -72,7 +62,7 @@ docker run -it --rm \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||
--entrypoint="install" \
|
||||
appwrite/appwrite:1.8.1
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
### Windows
|
||||
@@ -84,128 +74,78 @@ docker run -it --rm ^
|
||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||
--entrypoint="install" ^
|
||||
appwrite/appwrite:1.8.1
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
|
||||
```powershell
|
||||
docker run -it --rm `
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||
--entrypoint="install" `
|
||||
appwrite/appwrite:1.8.1
|
||||
docker run -it --rm ,
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock ,
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ,
|
||||
--entrypoint="install" ,
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
||||
|
||||
|
||||
需要自定义容器构架,请查看我们的 Docker [环境变量](https://appwrite.io/docs/environment-variables) 文档。您还可以参考我们的 [docker-compose.yml](https://appwrite.io/install/compose) 和 [.env](https://appwrite.io/install/env) 文件手动设置环境。
|
||||
|
||||
### 从旧版本升级
|
||||
|
||||
如果您从旧版本升级 Appwrite 服务器,则应在设置完成后使用 Appwrite 迁移工具。有关这方面的更多信息,请查看 [安装文档](https://appwrite.io/docs/self-hosting)。
|
||||
|
||||
## 一键配置
|
||||
|
||||
除了在本地运行 Appwrite,您还可以使用预配置的设置启动 Appwrite。这样可以让您快速启动并运行 Appwrite,而无需在本地计算机上安装 Docker。
|
||||
|
||||
请从以下提供商中选择一个:
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://marketplace.digitalocean.com/apps/appwrite">
|
||||
<img width="50" height="39" src="public/images/integrations/digitalocean-logo.svg" alt="DigitalOcean Logo" />
|
||||
<br /><sub><b>DigitalOcean</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://www.linode.com/marketplace/apps/appwrite/appwrite/">
|
||||
<img width="50" height="39" src="public/images/integrations/akamai-logo.svg" alt="Akamai Logo" />
|
||||
<br /><sub><b>Akamai Compute</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://aws.amazon.com/marketplace/pp/prodview-2hiaeo2px4md6">
|
||||
<img width="50" height="39" src="public/images/integrations/aws-logo.svg" alt="AWS Logo" />
|
||||
<br /><sub><b>AWS Marketplace</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
如果您从旧版本升级 Appwrite 服务器,则应在设置完成后使用 Appwrite 迁移工具。有关这方面的更多信息,请查看 [安装文档](https://appwrite.io/docs/installation)。
|
||||
|
||||
## 入门
|
||||
|
||||
开始使用 Appwrite 只需要在控制台创建一个新项目,选择开发平台,然后抓取我们的开发套件。您可以从以下的教程中找到你喜欢的平台开始使用 Appwrite。
|
||||
|
||||
| 类别 | 技术 |
|
||||
| ------------------ | --------------------------------------------------------------------------- |
|
||||
| **Web 应用** | [Web 快速开始](https://appwrite.io/docs/quick-starts/web) |
|
||||
| | [Next.js 快速开始](https://appwrite.io/docs/quick-starts/nextjs) |
|
||||
| | [React 快速开始](https://appwrite.io/docs/quick-starts/react) |
|
||||
| | [Vue.js 快速开始](https://appwrite.io/docs/quick-starts/vue) |
|
||||
| | [Nuxt 快速开始](https://appwrite.io/docs/quick-starts/nuxt) |
|
||||
| | [SvelteKit 快速开始](https://appwrite.io/docs/quick-starts/sveltekit) |
|
||||
| | [Refine 快速开始](https://appwrite.io/docs/quick-starts/refine) |
|
||||
| | [Angular 快速开始](https://appwrite.io/docs/quick-starts/angular) |
|
||||
| **苹果于安卓应用** | [React Native 快速开始](https://appwrite.io/docs/quick-starts/react-native) |
|
||||
| | [Flutter 快速开始](https://appwrite.io/docs/quick-starts/flutter) |
|
||||
| | [Apple 快速开始](https://appwrite.io/docs/quick-starts/apple) |
|
||||
| | [Android 快速开始](https://appwrite.io/docs/quick-starts/android) |
|
||||
| **服务器** | [Node.js 快速开始](https://appwrite.io/docs/quick-starts/node) |
|
||||
| | [Python 快速开始](https://appwrite.io/docs/quick-starts/python) |
|
||||
| | [.NET 快速开始](https://appwrite.io/docs/quick-starts/dotnet) |
|
||||
| | [Dart 快速开始](https://appwrite.io/docs/quick-starts/dart) |
|
||||
| | [Ruby 快速开始](https://appwrite.io/docs/quick-starts/ruby) |
|
||||
| | [Deno 快速开始](https://appwrite.io/docs/quick-starts/deno) |
|
||||
| | [PHP 快速开始](https://appwrite.io/docs/quick-starts/php) |
|
||||
| | [Kotlin 快速开始](https://appwrite.io/docs/quick-starts/kotlin) |
|
||||
| | [Swift 快速开始](https://appwrite.io/docs/quick-starts/swift) |
|
||||
* [开始使用 Web](https://appwrite.io/docs/getting-started-for-web)
|
||||
* [开始使用 Flutter](https://appwrite.io/docs/getting-started-for-flutter)
|
||||
* [开始使用 Apple](https://appwrite.io/docs/getting-started-for-apple)
|
||||
* [开始使用 Android](https://appwrite.io/docs/getting-started-for-android)
|
||||
* [开始使用 Server](https://appwrite.io/docs/getting-started-for-server)
|
||||
* [开始使用 CLI](https://appwrite.io/docs/command-line)
|
||||
|
||||
### 软件服务
|
||||
|
||||
- [**帐户**](https://appwrite.io/docs/references/cloud/client-web/account) -管理当前用户的帐户和登录方式。跟踪和管理用户 Session,登录设备,登录方法和查看相关记录。
|
||||
- [**用户**](https://appwrite.io/docs/server/users) - 在以管理员模式登录时管理和列出所有用户。
|
||||
- [**团队**](https://appwrite.io/docs/references/cloud/client-web/teams) - 管理用户分组。邀请成员,管理团队中的用户权限和用户角色。
|
||||
- [**数据库**](https://appwrite.io/docs/references/cloud/client-web/databases) - 管理数据库文档和文档集。用检索界面来对文档和文档集进行读取,创建,更新,和删除。
|
||||
- [**贮存**](https://appwrite.io/docs/references/cloud/client-web/storage) - 管理文件的阅读、创建、删除和预览。设置文件的预览来满足程序的个性化需求。所有文件都由 ClamAV 扫描并安全存储和加密。
|
||||
- [**云函数**](https://appwrite.io/docs/server/functions) - 在安全,隔离的环境中运行自定义代码。这些代码可以被事件,CRON,或者手动操作触发。
|
||||
- [**消息传递**](https://appwrite.io/docs/references/cloud/client-web/messaging) - 使用 Appwrite 消息传递功能通过推送通知、电子邮件和短信与用户进行通信。
|
||||
- [**语言适配**](https://appwrite.io/docs/references/cloud/client-web/locale) - 根据用户所在的的国家和地区做出合适的语言适配。
|
||||
- [**头像**](https://appwrite.io/docs/references/cloud/client-web/avatars) -管理用户头像、国家旗帜、浏览器图标、信用卡符号,和生成二维码。
|
||||
- [**MCP**](https://appwrite.io/docs/tooling/mcp) - 使用 Appwrite 的模型上下文协议(Model Context Protocol)服务器,允许大语言模型(LLM)和 AI 工具(如 Claude Desktop、Cursor 和 Windsurf Editor)通过自然语言直接与您的 Appwrite 项目交互。
|
||||
- [**站点**](https://appwrite.io/docs/products/sites) - 直接从 Appwrite 开发、部署和扩展您的 Web 应用程序,与您的后端一起。
|
||||
如需完整的 API 界面文档,请访问 [https://appwrite.io/docs](https://appwrite.io/docs)。如需更多教程、新闻和公告,请订阅我们的 [博客](https://medium.com/appwrite-io) 和 加入我们的[Discord 社区](https://discord.gg/GSeTUeA)。
|
||||
* [**帐户**](https://appwrite.io/docs/client/account) -管理当前用户的帐户和登录方式。跟踪和管理用户 Session,登录设备,登录方法和查看相关记录。
|
||||
* [**用户**](https://appwrite.io/docs/server/users) - 在以管理员模式登录时管理和列出所有用户。
|
||||
* [**团队**](https://appwrite.io/docs/client/teams) - 管理用户分组。邀请成员,管理团队中的用户权限和用户角色。
|
||||
* [**数据库**](https://appwrite.io/docs/client/databases) - 管理数据库文档和文档集。用检索界面来对文档和文档集进行读取,创建,更新,和删除。
|
||||
* [**贮存**](https://appwrite.io/docs/client/storage) - 管理文件的阅读、创建、删除和预览。设置文件的预览来满足程序的个性化需求。所有文件都由 ClamAV 扫描并安全存储和加密。
|
||||
* [**云函数**](https://appwrite.io/docs/server/functions) - 在安全,隔离的环境中运行自定义代码。这些代码可以被事件,CRON,或者手动操作触发。
|
||||
* [**语言适配**](https://appwrite.io/docs/client/locale) - 根据用户所在的的国家和地区做出合适的语言适配。
|
||||
* [**头像**](https://appwrite.io/docs/client/avatars) -管理用户头像、国家旗帜、浏览器图标、信用卡符号,和生成二维码。
|
||||
如需完整的 API 界面文档,请访问 [https://appwrite.io/docs](https://appwrite.io/docs)。如需更多教程、新闻和公告,请订阅我们的 [博客](https://medium.com/appwrite-io) 和 加入我们的[Discord 社区](https://discord.gg/GSeTUeA)。
|
||||
|
||||
### 开发套件
|
||||
|
||||
以下是当前支持的平台和语言列表。如果您想帮助我们为您选择的平台添加支持,您可以访问我们的 [SDK 生成器](https://github.com/appwrite/sdk-generator) 项目并查看我们的 [贡献指南](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md)。
|
||||
|
||||
#### 客户端
|
||||
|
||||
- :white_check_mark: [Web](https://github.com/appwrite/sdk-for-web) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Flutter](https://github.com/appwrite/sdk-for-flutter) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Android](https://github.com/appwrite/sdk-for-android) (由 Appwrite 团队维护)
|
||||
* ✅ [Web](https://github.com/appwrite/sdk-for-web) (由 Appwrite 团队维护)
|
||||
* ✅ [Flutter](https://github.com/appwrite/sdk-for-flutter) (由 Appwrite 团队维护)
|
||||
* ✅ [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护)
|
||||
* ✅ [Android](https://github.com/appwrite/sdk-for-android) (由 Appwrite 团队维护)
|
||||
|
||||
#### 服务器
|
||||
|
||||
- :white_check_mark: [NodeJS](https://github.com/appwrite/sdk-for-node) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [PHP](https://github.com/appwrite/sdk-for-php) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Dart](https://github.com/appwrite/sdk-for-dart) - (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Deno](https://github.com/appwrite/sdk-for-deno) - **公测** (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Ruby](https://github.com/appwrite/sdk-for-ruby) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Python](https://github.com/appwrite/sdk-for-python) (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Kotlin](https://github.com/appwrite/sdk-for-kotlin) - **公测** (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护)
|
||||
- :white_check_mark: [.NET](https://github.com/appwrite/sdk-for-dotnet) - **公测** (由 Appwrite 团队维护)
|
||||
* ✅ [NodeJS](https://github.com/appwrite/sdk-for-node) (由 Appwrite 团队维护)
|
||||
* ✅ [PHP](https://github.com/appwrite/sdk-for-php) (由 Appwrite 团队维护)
|
||||
* ✅ [Dart](https://github.com/appwrite/sdk-for-dart) - (由 Appwrite 团队维护)
|
||||
* ✅ [Deno](https://github.com/appwrite/sdk-for-deno) - **公测** (由 Appwrite 团队维护)
|
||||
* ✅ [Ruby](https://github.com/appwrite/sdk-for-ruby) (由 Appwrite 团队维护)
|
||||
* ✅ [Python](https://github.com/appwrite/sdk-for-python) (由 Appwrite 团队维护)
|
||||
* ✅ [Kotlin](https://github.com/appwrite/sdk-for-kotlin) - **公测** (由 Appwrite 团队维护)
|
||||
* ✅ [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护)
|
||||
* ✅ [.NET](https://github.com/appwrite/sdk-for-dotnet) - **公测** (由 Appwrite 团队维护)
|
||||
|
||||
#### 开发者社区
|
||||
* ✅ [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (维护者 [Michael Gangolf](https://github.com/m1ga/))
|
||||
* ✅ [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (维护者 [fenix-hub @GodotNuts](https://github.com/fenix-hub))
|
||||
|
||||
- :white_check_mark: [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (维护者 [Michael Gangolf](https://github.com/m1ga/))
|
||||
- :white_check_mark: [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (维护者 [fenix-hub @GodotNuts](https://github.com/fenix-hub))
|
||||
找不到需要的的 SDK? - 欢迎通过发起PR来帮助我们完善Appwrite的软件生态环境 [SDK 生成器](https://github.com/appwrite/sdk-generator)!
|
||||
|
||||
找不到需要的的 SDK? - 欢迎通过发起 PR 来帮助我们完善 Appwrite 的软件生态环境 [SDK 生成器](https://github.com/appwrite/sdk-generator)!
|
||||
|
||||
## 软件架构
|
||||
|
||||
@@ -217,17 +157,17 @@ Appwrite API 界面层利用后台缓存和任务委派来提供极速的响应
|
||||
|
||||
## 贡献代码
|
||||
|
||||
为了确保正确审查,所有代码贡献 - 包括来自具有直接提交更改权限的贡献者 - 都必须提交 PR 请求并在合并分支之前得到核心开发人员的批准。
|
||||
所有代码贡献 - 包括来自具有直接提交更改权限的贡献者 - 都必须提交PR请求并在合并分支之前得到核心开发人员的批准。这是为了确保正确审查所有代码。
|
||||
|
||||
我们欢迎所有人提交 PR!如果您愿意提供帮助,可以在 [贡献指南](CONTRIBUTING.md) 中了解有关如何为项目做出贡献的更多信息。
|
||||
我们欢迎所有人提交PR!如果您愿意提供帮助,可以在 [贡献指南](CONTRIBUTING.md) 中了解有关如何为项目做出贡献的更多信息。
|
||||
|
||||
## 安全
|
||||
|
||||
为了保护您的隐私,请避免在 GitHub 上发布安全问题。发送问题至 security@appwrite.io,我们将为您做更细致的解答。
|
||||
为了保护您的隐私,请避免在GitHub 上发布安全问题。发送问题至 security@appwrite.io,我们将为您做更细致的解答。
|
||||
|
||||
## 订阅我们
|
||||
|
||||
加入我们在世界各地不断发展的社区!请参阅我们的官方 [博客](https://medium.com/appwrite-io)。在 [Twitter](https://twitter.com/appwrite)、[Facebook 页面](https://www.facebook.com/appwrite.io)、[Facebook 群组](https://www.facebook.com/appwrite.io/groups/)、[开发者社区](https://dev.to/appwrite) 等平台订阅我们或加入我们的 [Discord 社区](https://discord.gg/GSeTUeA) 以获得更多帮助,想法和讨论。
|
||||
加入我们在世界各地不断发展的社区!请参阅我们的官方 [博客](https://medium.com/appwrite-io)。在 [Twitter](https://twitter.com/appwrite)、[Facebook 页面](https://www.facebook.com/appwrite.io)、[Facebook 群组](https://www.facebook)、[开发者社区](https://dev.to/appwrite) 等平台订阅我们或加入我们的 [Discord 社区](https://discord.gg/GSeTUeA) 以获得更多帮助,想法和讨论。
|
||||
|
||||
## 版权说明
|
||||
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
> We just announced DB operators for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-db-operators)
|
||||
|
||||
> Appwrite Cloud is now Generally Available - [Learn more](https://appwrite.io/cloud-ga)
|
||||
|
||||
> [Get started with Appwrite](https://apwr.dev/appcloud)
|
||||
> It's going to get cloudy! 🌩 ☂️
|
||||
> The Appwrite Cloud is coming soon! You can learn more about our upcoming hosted solution and signup for free credits at: https://appwrite.io/cloud
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://appwrite.io" target="_blank"><img src="./public/images/banner.png" alt="Appwrite banner, with logo and text saying "The Developer's Cloud"></a>
|
||||
<a href="https://appwrite.io" target="_blank"><img width="260" height="39" src="https://appwrite.io/images/appwrite.svg" alt="Appwrite Logo"></a>
|
||||
<br />
|
||||
<br />
|
||||
<b>Appwrite is a best-in-class, developer-first platform that gives builders everything they need to create scalable, stable, and production-ready software, fast.</b>
|
||||
<b>A complete backend solution for your [Flutter / Vue / Angular / React / iOS / Android / *ANY OTHER*] app</b>
|
||||
<br />
|
||||
<br />
|
||||
</p>
|
||||
|
||||
|
||||
<!-- [](https://travis-ci.com/appwrite/appwrite) -->
|
||||
|
||||
[](https://appwrite.io/company/careers)
|
||||
[](https://hacktoberfest.appwrite.io)
|
||||
[](https://appwrite.io/discord?r=Github)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://twitter.com/appwrite)
|
||||
[](https://hacktoberfest.appwrite.io)
|
||||
[](https://appwrite.io/discord?r=Github)
|
||||
[](https://github.com/appwrite/appwrite/actions)
|
||||
[](https://twitter.com/appwrite)
|
||||
|
||||
<!-- [](https://hub.docker.com/r/appwrite/appwrite) -->
|
||||
<!-- [](docs/tutorials/add-translations.md) -->
|
||||
@@ -28,26 +25,33 @@
|
||||
|
||||
English | [简体中文](README-CN.md)
|
||||
|
||||
Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.
|
||||
[**Appwrite 1.0 has been released! Learn what's new!**](https://appwrite.io/1.0)
|
||||
|
||||
Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and [more services](https://appwrite.io/docs).
|
||||
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
|
||||
|
||||

|
||||
Using Appwrite, you can easily integrate your app with user authentication & multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs).
|
||||
|
||||
Find out more at: [https://appwrite.io](https://appwrite.io).
|
||||
<p align="center">
|
||||
<br />
|
||||
<a href="https://www.producthunt.com/posts/appwrite-2?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-appwrite-2" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=360315&theme=light&period=daily" alt="Appwrite - 100% open source alternative for Firebase | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
<br />
|
||||
<br />
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
Find out more at: [https://appwrite.io](https://appwrite.io)
|
||||
|
||||
Table of Contents:
|
||||
|
||||
- [Installation \& Setup](#installation--setup)
|
||||
- [Self-Hosting](#self-hosting)
|
||||
- [Installation](#installation)
|
||||
- [Unix](#unix)
|
||||
- [Windows](#windows)
|
||||
- [CMD](#cmd)
|
||||
- [PowerShell](#powershell)
|
||||
- [Upgrade from an Older Version](#upgrade-from-an-older-version)
|
||||
- [One-Click Setups](#one-click-setups)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Products](#products)
|
||||
- [Services](#services)
|
||||
- [SDKs](#sdks)
|
||||
- [Client](#client)
|
||||
- [Server](#server)
|
||||
@@ -58,15 +62,11 @@ Table of Contents:
|
||||
- [Follow Us](#follow-us)
|
||||
- [License](#license)
|
||||
|
||||
## Installation & Setup
|
||||
## Installation
|
||||
|
||||
The easiest way to get started with Appwrite is by [signing up for Appwrite Cloud](https://cloud.appwrite.io/). While Appwrite Cloud is in public beta, you can build with Appwrite completely free, and we won't collect your credit card information.
|
||||
Appwrite backend server is designed to run in a container environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool like Kubernetes, Docker Swarm, or Rancher.
|
||||
|
||||
## Self-Hosting
|
||||
|
||||
Appwrite is designed to run in a containerized environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool, such as [Kubernetes](https://kubernetes.io/docs/home/), [Docker Swarm](https://docs.docker.com/engine/swarm/), or [Rancher](https://rancher.com/docs/).
|
||||
|
||||
Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
|
||||
The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
|
||||
|
||||
### Unix
|
||||
|
||||
@@ -75,7 +75,7 @@ docker run -it --rm \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||
--entrypoint="install" \
|
||||
appwrite/appwrite:1.8.1
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
### Windows
|
||||
@@ -87,7 +87,7 @@ docker run -it --rm ^
|
||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||
--entrypoint="install" ^
|
||||
appwrite/appwrite:1.8.1
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
@@ -97,20 +97,20 @@ docker run -it --rm `
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||
--entrypoint="install" `
|
||||
appwrite/appwrite:1.8.1
|
||||
appwrite/appwrite:1.0.3
|
||||
```
|
||||
|
||||
Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation.
|
||||
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after installation completes.
|
||||
|
||||
For advanced production and custom installation, check out our Docker [environment variables](https://appwrite.io/docs/environment-variables) docs. You can also use our public [docker-compose.yml](https://appwrite.io/install/compose) and [.env](https://appwrite.io/install/env) files to manually set up an environment.
|
||||
|
||||
### Upgrade from an Older Version
|
||||
|
||||
If you are upgrading your Appwrite server from an older version, you should use the Appwrite migration tool once your setup is completed. For more information regarding this, check out the [Installation Docs](https://appwrite.io/docs/self-hosting).
|
||||
If you are upgrading your Appwrite server from an older version, you should use the Appwrite migration tool once your setup is completed. For more information regarding this, check out the [Installation Docs](https://appwrite.io/docs/installation).
|
||||
|
||||
## One-Click Setups
|
||||
|
||||
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running quickly with Appwrite without installing Docker on your local machine.
|
||||
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
|
||||
|
||||
Choose from one of the providers below:
|
||||
|
||||
@@ -123,15 +123,9 @@ Choose from one of the providers below:
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://www.linode.com/marketplace/apps/appwrite/appwrite/">
|
||||
<img width="50" height="39" src="public/images/integrations/akamai-logo.svg" alt="Akamai Logo" />
|
||||
<br /><sub><b>Akamai Compute</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://aws.amazon.com/marketplace/pp/prodview-2hiaeo2px4md6">
|
||||
<img width="50" height="39" src="public/images/integrations/aws-logo.svg" alt="AWS Logo" />
|
||||
<br /><sub><b>AWS Marketplace</b></sub></a>
|
||||
<a href="https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod">
|
||||
<img width="50" height="39" src="public/images/integrations/gitpod-logo.svg" alt="Gitpod Logo" />
|
||||
<br /><sub><b>Gitpod</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -141,91 +135,70 @@ Choose from one of the providers below:
|
||||
|
||||
Getting started with Appwrite is as easy as creating a new project, choosing your platform, and integrating its SDK into your code. You can easily get started with your platform of choice by reading one of our Getting Started tutorials.
|
||||
|
||||
| Platform | Technology |
|
||||
| --------------------- | ---------------------------------------------------------------------------------- |
|
||||
| **Web app** | [Quick start for Web](https://appwrite.io/docs/quick-starts/web) |
|
||||
| | [Quick start for Next.js](https://appwrite.io/docs/quick-starts/nextjs) |
|
||||
| | [Quick start for React](https://appwrite.io/docs/quick-starts/react) |
|
||||
| | [Quick start for Vue.js](https://appwrite.io/docs/quick-starts/vue) |
|
||||
| | [Quick start for Nuxt](https://appwrite.io/docs/quick-starts/nuxt) |
|
||||
| | [Quick start for SvelteKit](https://appwrite.io/docs/quick-starts/sveltekit) |
|
||||
| | [Quick start for Refine](https://appwrite.io/docs/quick-starts/refine) |
|
||||
| | [Quick start for Angular](https://appwrite.io/docs/quick-starts/angular) |
|
||||
| **Mobile and Native** | [Quick start for React Native](https://appwrite.io/docs/quick-starts/react-native) |
|
||||
| | [Quick start for Flutter](https://appwrite.io/docs/quick-starts/flutter) |
|
||||
| | [Quick start for Apple](https://appwrite.io/docs/quick-starts/apple) |
|
||||
| | [Quick start for Android](https://appwrite.io/docs/quick-starts/android) |
|
||||
| **Server** | [Quick start for Node.js](https://appwrite.io/docs/quick-starts/node) |
|
||||
| | [Quick start for Python](https://appwrite.io/docs/quick-starts/python) |
|
||||
| | [Quick start for .NET](https://appwrite.io/docs/quick-starts/dotnet) |
|
||||
| | [Quick start for Dart](https://appwrite.io/docs/quick-starts/dart) |
|
||||
| | [Quick start for Ruby](https://appwrite.io/docs/quick-starts/ruby) |
|
||||
| | [Quick start for Deno](https://appwrite.io/docs/quick-starts/deno) |
|
||||
| | [Quick start for PHP](https://appwrite.io/docs/quick-starts/php) |
|
||||
| | [Quick start for Kotlin](https://appwrite.io/docs/quick-starts/kotlin) |
|
||||
| | [Quick start for Swift](https://appwrite.io/docs/quick-starts/swift) |
|
||||
- [Getting Started for Web](https://appwrite.io/docs/getting-started-for-web)
|
||||
- [Getting Started for Flutter](https://appwrite.io/docs/getting-started-for-flutter)
|
||||
- [Getting Started for Apple](https://appwrite.io/docs/getting-started-for-apple)
|
||||
- [Getting Started for Android](https://appwrite.io/docs/getting-started-for-android)
|
||||
- [Getting Started for Server](https://appwrite.io/docs/getting-started-for-server)
|
||||
- [Getting Started for CLI](https://appwrite.io/docs/command-line)
|
||||
|
||||
### Products
|
||||
### Services
|
||||
|
||||
- [**Account**](https://appwrite.io/docs/references/cloud/client-web/account) - Manage current user authentication and account. Track and manage the user sessions, devices, sign-in methods, and security logs.
|
||||
- [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when building backend integrations with Server SDKs.
|
||||
- [**Teams**](https://appwrite.io/docs/references/cloud/client-web/teams) - Manage and group users in teams. Manage memberships, invites, and user roles within a team.
|
||||
- [**Databases**](https://appwrite.io/docs/references/cloud/client-web/databases) - Manage databases, collections, and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
- [**Storage**](https://appwrite.io/docs/references/cloud/client-web/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to perfectly fit your app. All files are scanned by ClamAV and stored in a secure and encrypted way.
|
||||
- [**Functions**](https://appwrite.io/docs/references/cloud/server-nodejs/functions) - Customize your Appwrite project by executing your custom code in a secure, isolated environment. You can trigger your code on any Appwrite system event either manually or using a CRON schedule.
|
||||
- [**Messaging**](https://appwrite.io/docs/references/cloud/client-web/messaging) - Communicate with your users through push notifications, emails, and SMS text messages using Appwrite Messaging.
|
||||
- [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases, and more.
|
||||
- [**Locale**](https://appwrite.io/docs/references/cloud/client-web/locale) - Track your user's location and manage your app locale-based data.
|
||||
- [**Avatars**](https://appwrite.io/docs/references/cloud/client-web/avatars) - Manage your users' avatars, countries' flags, browser icons, and credit card symbols. Generate QR codes from links or plaintext strings.
|
||||
- [**MCP**](https://appwrite.io/docs/tooling/mcp) - Use Appwrite's Model Context Protocol (MCP) server to allow LLMs and AI tools like Claude Desktop, Cursor, and Windsurf Editor to directly interact with your Appwrite project through natural language.
|
||||
- [**Sites**](https://appwrite.io/docs/products/sites) - Develop, deploy, and scale your web applications directly from Appwrite, alongside your backend.
|
||||
- [**Account**](https://appwrite.io/docs/client/account) - Manage current user authentication and account. Track and manage the user sessions, devices, sign-in methods, and security logs.
|
||||
- [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when in admin mode.
|
||||
- [**Teams**](https://appwrite.io/docs/client/teams) - Manage and group users in teams. Manage memberships, invites, and user roles within a team.
|
||||
- [**Databases**](https://appwrite.io/docs/client/databases) - Manage databases, collections and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
- [**Storage**](https://appwrite.io/docs/client/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to fit your app perfectly. All files are scanned by ClamAV and stored in a secure and encrypted way.
|
||||
- [**Functions**](https://appwrite.io/docs/server/functions) - Customize your Appwrite server by executing your custom code in a secure, isolated environment. You can trigger your code on any Appwrite system event, manually or using a CRON schedule.
|
||||
- [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases and more.
|
||||
- [**Locale**](https://appwrite.io/docs/client/locale) - Track your user's location, and manage your app locale-based data.
|
||||
- [**Avatars**](https://appwrite.io/docs/client/avatars) - Manage your users' avatars, countries' flags, browser icons, credit card symbols, and generate QR codes.
|
||||
|
||||
For the complete API documentation, visit [https://appwrite.io/docs](https://appwrite.io/docs). For more tutorials, news and announcements check out our [blog](https://medium.com/appwrite-io) and [Discord Server](https://discord.gg/GSeTUeA).
|
||||
|
||||
### SDKs
|
||||
|
||||
Below is a list of currently supported platforms and languages. If you would like to help us add support to your platform of choice, you can go over to our [SDK Generator](https://github.com/appwrite/sdk-generator) project and view our [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md).
|
||||
Below is a list of currently supported platforms and languages. If you wish to help us add support to your platform of choice, you can go over to our [SDK Generator](https://github.com/appwrite/sdk-generator) project and view our [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md).
|
||||
|
||||
#### Client
|
||||
|
||||
- :white_check_mark: [Web](https://github.com/appwrite/sdk-for-web) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Flutter](https://github.com/appwrite/sdk-for-flutter) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Apple](https://github.com/appwrite/sdk-for-apple) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Android](https://github.com/appwrite/sdk-for-android) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [React Native](https://github.com/appwrite/sdk-for-react-native) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [Web](https://github.com/appwrite/sdk-for-web) (Maintained by the Appwrite Team)
|
||||
- ✅ [Flutter](https://github.com/appwrite/sdk-for-flutter) (Maintained by the Appwrite Team)
|
||||
- ✅ [Apple](https://github.com/appwrite/sdk-for-apple) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [Android](https://github.com/appwrite/sdk-for-android) (Maintained by the Appwrite Team)
|
||||
|
||||
#### Server
|
||||
|
||||
- :white_check_mark: [NodeJS](https://github.com/appwrite/sdk-for-node) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [PHP](https://github.com/appwrite/sdk-for-php) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Dart](https://github.com/appwrite/sdk-for-dart) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Deno](https://github.com/appwrite/sdk-for-deno) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Ruby](https://github.com/appwrite/sdk-for-ruby) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Python](https://github.com/appwrite/sdk-for-python) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [Swift](https://github.com/appwrite/sdk-for-swift) (Maintained by the Appwrite Team)
|
||||
- :white_check_mark: [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [NodeJS](https://github.com/appwrite/sdk-for-node) (Maintained by the Appwrite Team)
|
||||
- ✅ [PHP](https://github.com/appwrite/sdk-for-php) (Maintained by the Appwrite Team)
|
||||
- ✅ [Dart](https://github.com/appwrite/sdk-for-dart) - (Maintained by the Appwrite Team)
|
||||
- ✅ [Deno](https://github.com/appwrite/sdk-for-deno) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [Ruby](https://github.com/appwrite/sdk-for-ruby) (Maintained by the Appwrite Team)
|
||||
- ✅ [Python](https://github.com/appwrite/sdk-for-python) (Maintained by the Appwrite Team)
|
||||
- ✅ [Kotlin](https://github.com/appwrite/sdk-for-kotlin) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [Apple](https://github.com/appwrite/sdk-for-apple) - **Beta** (Maintained by the Appwrite Team)
|
||||
- ✅ [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Experimental** (Maintained by the Appwrite Team)
|
||||
|
||||
#### Community
|
||||
|
||||
- :white_check_mark: [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/))
|
||||
- :white_check_mark: [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (Maintained by [fenix-hub @GodotNuts](https://github.com/fenix-hub))
|
||||
- ✅ [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/))
|
||||
- ✅ [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (Maintained by [fenix-hub @GodotNuts](https://github.com/fenix-hub))
|
||||
|
||||
Looking for more SDKs? - Help us by contributing a pull request to our [SDK Generator](https://github.com/appwrite/sdk-generator)!
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||

|
||||
|
||||
Appwrite uses a microservices architecture that was designed for easy scaling and delegation of responsibilities. In addition, Appwrite supports multiple APIs, such as REST, WebSocket, and GraphQL to allow you to interact with your resources by leveraging your existing knowledge and protocols of choice.
|
||||
Appwrite uses a microservices architecture that was designed for easy scaling and delegation of responsibilities. In addition, Appwrite supports multiple APIs (REST, WebSocket, and GraphQL-soon) to allow you to interact with your resources by leveraging your existing knowledge and protocols of choice.
|
||||
|
||||
The Appwrite API layer was designed to be extremely fast by leveraging in-memory caching and delegating any heavy-lifting tasks to the Appwrite background workers. The background workers also allow you to precisely control your compute capacity and costs using a message queue to handle the load. You can learn more about our architecture in the [contribution guide](CONTRIBUTING.md#architecture-1).
|
||||
|
||||
## Contributing
|
||||
|
||||
All code contributions, including those of people having commit access, must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
|
||||
All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
|
||||
|
||||
We truly :heart: pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md).
|
||||
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md).
|
||||
|
||||
## Security
|
||||
|
||||
@@ -233,7 +206,7 @@ For security issues, kindly email us at [security@appwrite.io](mailto:security@a
|
||||
|
||||
## Follow Us
|
||||
|
||||
Join our growing community around the world! Check out our official [Blog](https://appwrite.io/blog). Follow us on [X](https://twitter.com/appwrite), [LinkedIn](https://www.linkedin.com/company/appwrite/), [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://appwrite.io/discord) for more help, ideas, and discussions.
|
||||
Join our growing community around the world! See our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/) , [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://discord.gg/GSeTUeA) for more help, ideas, and discussions.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+5
-10
@@ -2,16 +2,11 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| --------- | ------------------ |
|
||||
| <= 0.15.x | :x: |
|
||||
| 1.0.x | :white_check_mark: |
|
||||
| 1.1.x | :white_check_mark: |
|
||||
| 1.2.x | :white_check_mark: |
|
||||
| 1.3.x | :white_check_mark: |
|
||||
| 1.4.x | :white_check_mark: |
|
||||
| 1.5.x | :white_check_mark: |
|
||||
| 1.6.x | :white_check_mark: |
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| <= 0.10 | :x: |
|
||||
| 0.11.x | :white_check_mark: |
|
||||
| 0.12.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
+20
-329
@@ -1,341 +1,32 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/init.php';
|
||||
|
||||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Func;
|
||||
use Appwrite\Event\StatsResources;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Platform\Appwrite;
|
||||
use Appwrite\Runtimes\Runtimes;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Executor\Executor;
|
||||
use Swoole\Runtime;
|
||||
use Swoole\Timer;
|
||||
use Utopia\Cache\Adapter\Pool as CachePool;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DI\Dependency;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Service;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Queue\Broker\Pool as BrokerPool;
|
||||
use Utopia\Queue\Publisher;
|
||||
use Utopia\Registry\Registry;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
||||
|
||||
use function Swoole\Coroutine\run;
|
||||
|
||||
// overwriting runtimes to be architecture agnostic for CLI
|
||||
Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
|
||||
|
||||
// require controllers after overwriting runtimes
|
||||
require_once __DIR__ . '/controllers/general.php';
|
||||
|
||||
global $register;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\CLI;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
|
||||
$platform = new Appwrite();
|
||||
$args = $platform->getEnv('argv');
|
||||
Authorization::disable();
|
||||
|
||||
\array_shift($args);
|
||||
if (!isset($args[0])) {
|
||||
Console::error('Missing task name');
|
||||
Console::exit(1);
|
||||
}
|
||||
$cli = new CLI();
|
||||
|
||||
$taskName = $args[0];
|
||||
$platform->init(Service::TYPE_TASK);
|
||||
$cli = $platform->getCli();
|
||||
|
||||
$setResource = function (string $name, callable $callback, array $injections = []) use ($cli) {
|
||||
$dependency = new Dependency();
|
||||
$dependency->setName($name)->setCallback($callback);
|
||||
foreach ($injections as $injection) {
|
||||
$dependency->inject($injection);
|
||||
}
|
||||
$cli->setResource($dependency);
|
||||
};
|
||||
|
||||
$setResource('register', fn () => $register, []);
|
||||
|
||||
$setResource('cache', function ($pools) {
|
||||
$list = Config::getParam('pools-cache', []);
|
||||
$adapters = [];
|
||||
|
||||
foreach ($list as $value) {
|
||||
$adapters[] = new CachePool($pools->get($value));
|
||||
}
|
||||
|
||||
return new Cache(new Sharding($adapters));
|
||||
}, ['pools']);
|
||||
|
||||
$setResource('pools', function (Registry $register) {
|
||||
return $register->get('pools');
|
||||
}, ['register']);
|
||||
|
||||
$setResource('authorization', function () {
|
||||
$authorization = new Authorization();
|
||||
$authorization->disable();
|
||||
return $authorization;
|
||||
}, []);
|
||||
|
||||
$setResource('dbForPlatform', function ($pools, $cache, $authorization) {
|
||||
$sleep = 3;
|
||||
$maxAttempts = 5;
|
||||
$attempts = 0;
|
||||
$ready = false;
|
||||
|
||||
do {
|
||||
$attempts++;
|
||||
try {
|
||||
// Prepare database connection
|
||||
$adapter = new DatabasePool($pools->get('console'));
|
||||
$dbForPlatform = new Database($adapter, $cache);
|
||||
|
||||
$dbForPlatform
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setNamespace('_console')
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', 'console');
|
||||
$dbForPlatform->setDocumentType('users', User::class);
|
||||
|
||||
// Ensure tables exist
|
||||
$collections = Config::getParam('collections', [])['console'];
|
||||
$last = \array_key_last($collections);
|
||||
|
||||
if (!($dbForPlatform->exists($dbForPlatform->getDatabase(), $last))) { /** TODO cache ready variable using registry */
|
||||
throw new Exception('Tables not ready yet.');
|
||||
}
|
||||
|
||||
$ready = true;
|
||||
} catch (\Throwable $err) {
|
||||
Console::warning($err->getMessage());
|
||||
sleep($sleep);
|
||||
}
|
||||
} while ($attempts < $maxAttempts && !$ready);
|
||||
|
||||
if (!$ready) {
|
||||
throw new Exception("Console is not ready yet. Please try again later.");
|
||||
}
|
||||
|
||||
return $dbForPlatform;
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
$setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
}, []);
|
||||
|
||||
$setResource(
|
||||
'isResourceBlocked',
|
||||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false,
|
||||
[]
|
||||
);
|
||||
|
||||
$setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) {
|
||||
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
|
||||
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) {
|
||||
if ($project->isEmpty() || $project->getId() === 'console') {
|
||||
return $dbForPlatform;
|
||||
}
|
||||
|
||||
try {
|
||||
$dsn = new DSN($project->getAttribute('database'));
|
||||
} catch (\InvalidArgumentException) {
|
||||
// TODO: Temporary until all projects are using shared tables
|
||||
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
|
||||
}
|
||||
|
||||
if (isset($databases[$dsn->getHost()])) {
|
||||
$database = $databases[$dsn->getHost()];
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
if (\in_array($dsn->getHost(), $sharedTables)) {
|
||||
$database
|
||||
->setSharedTables(true)
|
||||
->setTenant((int)$project->getSequence())
|
||||
->setNamespace($dsn->getParam('namespace'));
|
||||
} else {
|
||||
$database
|
||||
->setSharedTables(false)
|
||||
->setTenant(null)
|
||||
->setNamespace('_' . $project->getSequence());
|
||||
}
|
||||
|
||||
return $database;
|
||||
}
|
||||
|
||||
$adapter = new DatabasePool($pools->get($dsn->getHost()));
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$databases[$dsn->getHost()] = $database;
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
if (\in_array($dsn->getHost(), $sharedTables)) {
|
||||
$database
|
||||
->setSharedTables(true)
|
||||
->setTenant((int)$project->getSequence())
|
||||
->setNamespace($dsn->getParam('namespace'));
|
||||
} else {
|
||||
$database
|
||||
->setSharedTables(false)
|
||||
->setTenant(null)
|
||||
->setNamespace('_' . $project->getSequence());
|
||||
}
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setMetadata('host', \gethostname())
|
||||
->setMetadata('project', $project->getId());
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'authorization']);
|
||||
|
||||
$setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$database = null;
|
||||
|
||||
return function (?Document $project = null) use ($pools, $cache, $database, $authorization) {
|
||||
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$database->setTenant((int)$project->getSequence());
|
||||
return $database;
|
||||
}
|
||||
|
||||
$adapter = new DatabasePool($pools->get('logs'));
|
||||
$database = new Database($adapter, $cache);
|
||||
|
||||
$database
|
||||
->setDatabase(APP_DATABASE)
|
||||
->setAuthorization($authorization)
|
||||
->setSharedTables(true)
|
||||
->setNamespace('logsV1')
|
||||
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK)
|
||||
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
|
||||
|
||||
// set tenant
|
||||
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$database->setTenant((int)$project->getSequence());
|
||||
}
|
||||
|
||||
return $database;
|
||||
};
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
$setResource('publisher', function (Group $pools) {
|
||||
return new BrokerPool(publisher: $pools->get('publisher'));
|
||||
}, ['pools']);
|
||||
$setResource('publisherDatabases', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
$setResource('publisherFunctions', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
$setResource('publisherMigrations', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
$setResource('publisherStatsUsage', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
$setResource('publisherMessaging', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
$setResource('queueForStatsUsage', function (Publisher $publisher) {
|
||||
return new StatsUsage($publisher);
|
||||
}, ['publisher']);
|
||||
$setResource('queueForStatsResources', function (Publisher $publisher) {
|
||||
return new StatsResources($publisher);
|
||||
}, ['publisher']);
|
||||
$setResource('queueForFunctions', function (Publisher $publisher) {
|
||||
return new Func($publisher);
|
||||
}, ['publisher']);
|
||||
$setResource('queueForDeletes', function (Publisher $publisher) {
|
||||
return new Delete($publisher);
|
||||
}, ['publisher']);
|
||||
$setResource('queueForCertificates', function (Publisher $publisher) {
|
||||
return new Certificate($publisher);
|
||||
}, ['publisher']);
|
||||
$setResource('logError', function (Registry $register) {
|
||||
return function (Throwable $error, string $namespace, string $action) use ($register) {
|
||||
Console::error('[Error] Timestamp: ' . date('c', time()));
|
||||
Console::error('[Error] Type: ' . get_class($error));
|
||||
Console::error('[Error] Message: ' . $error->getMessage());
|
||||
Console::error('[Error] File: ' . $error->getFile());
|
||||
Console::error('[Error] Line: ' . $error->getLine());
|
||||
Console::error('[Error] Trace: ' . $error->getTraceAsString());
|
||||
|
||||
$logger = $register->get('logger');
|
||||
|
||||
if ($logger) {
|
||||
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
|
||||
$log = new Log();
|
||||
$log->setNamespace($namespace);
|
||||
$log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname()));
|
||||
$log->setVersion($version);
|
||||
$log->setType(Log::TYPE_ERROR);
|
||||
$log->setMessage($error->getMessage());
|
||||
|
||||
$log->addTag('code', $error->getCode());
|
||||
$log->addTag('verboseType', get_class($error));
|
||||
|
||||
$log->addExtra('file', $error->getFile());
|
||||
$log->addExtra('line', $error->getLine());
|
||||
$log->addExtra('trace', $error->getTraceAsString());
|
||||
$log->addExtra('detailedTrace', $error->getTrace());
|
||||
|
||||
if ($error->getPrevious() !== null) {
|
||||
if ($error->getPrevious()->getMessage() != $error->getMessage()) {
|
||||
$log->addExtra('previousMessage', $error->getPrevious()->getMessage());
|
||||
}
|
||||
$log->addExtra('previousFile', $error->getPrevious()->getFile());
|
||||
$log->addExtra('previousLine', $error->getPrevious()->getLine());
|
||||
}
|
||||
|
||||
$log->setAction($action);
|
||||
|
||||
$isProduction = System::getEnv('_APP_ENV', 'development') === 'production';
|
||||
$log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING);
|
||||
|
||||
try {
|
||||
$responseCode = $logger->addLog($log);
|
||||
Console::info('Error log pushed with status code: ' . $responseCode);
|
||||
} catch (Throwable $th) {
|
||||
Console::error('Error pushing log: ' . $th->getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
}, ['register']);
|
||||
|
||||
$setResource('executor', fn () => new Executor(), []);
|
||||
|
||||
$setResource('telemetry', fn () => new NoTelemetry(), []);
|
||||
include 'tasks/doctor.php';
|
||||
include 'tasks/maintenance.php';
|
||||
include 'tasks/install.php';
|
||||
include 'tasks/migrate.php';
|
||||
include 'tasks/sdks.php';
|
||||
include 'tasks/specs.php';
|
||||
include 'tasks/ssl.php';
|
||||
include 'tasks/vars.php';
|
||||
include 'tasks/usage.php';
|
||||
|
||||
$cli
|
||||
->error()
|
||||
->inject('error')
|
||||
->inject('logError')
|
||||
->action(function (Throwable $error, callable $logError) use ($taskName) {
|
||||
call_user_func_array($logError, [
|
||||
$error,
|
||||
'Task',
|
||||
$taskName,
|
||||
]);
|
||||
|
||||
Timer::clearAll();
|
||||
->task('version')
|
||||
->desc('Get the server version')
|
||||
->action(function () {
|
||||
Console::log(App::getEnv('_APP_VERSION', 'UNKNOWN'));
|
||||
});
|
||||
|
||||
$cli->shutdown()->action(fn () => Timer::clearAll());
|
||||
|
||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||
require_once __DIR__ . '/init/span.php';
|
||||
run($cli->run(...));
|
||||
$cli->run();
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'rest' => [
|
||||
'key' => 'rest',
|
||||
'name' => 'REST',
|
||||
],
|
||||
'graphql' => [
|
||||
'key' => 'graphql',
|
||||
'name' => 'GraphQL',
|
||||
],
|
||||
'realtime' => [
|
||||
'key' => 'realtime',
|
||||
'name' => 'Realtime',
|
||||
],
|
||||
];
|
||||
+4
-11
@@ -7,28 +7,21 @@ return [
|
||||
'name' => 'Email/Password',
|
||||
'key' => 'emailPassword',
|
||||
'icon' => '/images/users/email.png',
|
||||
'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateEmailPasswordSession',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateEmailSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
'magic-url' => [
|
||||
'name' => 'Magic URL',
|
||||
'key' => 'usersAuthMagicURL',
|
||||
'icon' => '/images/users/magic-url.png',
|
||||
'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateMagicURLToken',
|
||||
'enabled' => true,
|
||||
],
|
||||
'email-otp' => [
|
||||
'name' => 'Email (OTP)',
|
||||
'key' => 'emailOtp',
|
||||
'icon' => '/images/users/email.png',
|
||||
'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateEmailToken',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateMagicURLSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
'anonymous' => [
|
||||
'name' => 'Anonymous',
|
||||
'key' => 'anonymous',
|
||||
'icon' => '/images/users/anonymous.png',
|
||||
'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateAnonymousSession',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateAnonymousSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
'invites' => [
|
||||
@@ -49,7 +42,7 @@ return [
|
||||
'name' => 'Phone',
|
||||
'key' => 'phone',
|
||||
'icon' => '/images/users/phone.png',
|
||||
'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreatePhoneToken',
|
||||
'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreatePhoneSession',
|
||||
'enabled' => true,
|
||||
],
|
||||
];
|
||||
|
||||
@@ -2,21 +2,20 @@
|
||||
|
||||
return [
|
||||
// Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php
|
||||
'aa' => ['name' => 'Avant Browser', 'path' => __DIR__ . '/browsers/avant.png'],
|
||||
'an' => ['name' => 'Android WebView Beta', 'path' => __DIR__ . '/browsers/android-webview-beta.png'],
|
||||
'ch' => ['name' => 'Google Chrome', 'path' => __DIR__ . '/browsers/chrome.png'],
|
||||
'ci' => ['name' => 'Google Chrome (iOS)', 'path' => __DIR__ . '/browsers/chrome.png'],
|
||||
'cm' => ['name' => 'Google Chrome (Mobile)', 'path' => __DIR__ . '/browsers/chrome.png'],
|
||||
'cr' => ['name' => 'Chromium', 'path' => __DIR__ . '/browsers/chromium.png'],
|
||||
'ff' => ['name' => 'Mozilla Firefox', 'path' => __DIR__ . '/browsers/firefox.png'],
|
||||
'sf' => ['name' => 'Safari', 'path' => __DIR__ . '/browsers/safari.png'],
|
||||
'mf' => ['name' => 'Mobile Safari', 'path' => __DIR__ . '/browsers/safari.png'],
|
||||
'ps' => ['name' => 'Microsoft Edge', 'path' => __DIR__ . '/browsers/edge.png'],
|
||||
'oi' => ['name' => 'Microsoft Edge (iOS)', 'path' => __DIR__ . '/browsers/edge.png'],
|
||||
'om' => ['name' => 'Opera Mini', 'path' => __DIR__ . '/browsers/opera-mini.png'],
|
||||
'op' => ['name' => 'Opera', 'path' => __DIR__ . '/browsers/opera.png'],
|
||||
'on' => ['name' => 'Opera (Next)', 'path' => __DIR__ . '/browsers/opera.png'],
|
||||
|
||||
'aa' => __DIR__ . '/browsers/avant.png',
|
||||
'an' => __DIR__ . '/browsers/android-webview-beta.png',
|
||||
'ch' => __DIR__ . '/browsers/chrome.png',
|
||||
'ci' => __DIR__ . '/browsers/chrome.png', //Chrome Mobile iOS
|
||||
'cm' => __DIR__ . '/browsers/chrome.png', //Chrome Mobile
|
||||
'cr' => __DIR__ . '/browsers/chromium.png',
|
||||
'ff' => __DIR__ . '/browsers/firefox.png',
|
||||
'sf' => __DIR__ . '/browsers/safari.png',
|
||||
'mf' => __DIR__ . '/browsers/safari.png',
|
||||
'ps' => __DIR__ . '/browsers/edge.png',
|
||||
'oi' => __DIR__ . '/browsers/edge.png',
|
||||
'om' => __DIR__ . '/browsers/opera-mini.png',
|
||||
'op' => __DIR__ . '/browsers/opera.png',
|
||||
'on' => __DIR__ . '/browsers/opera.png',
|
||||
|
||||
/*
|
||||
'36' => '360 Phone Browser',
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'amex' => ['name' => 'American Express', 'path' => __DIR__ . '/credit-cards/amex.png'],
|
||||
'argencard' => ['name' => 'Argencard', 'path' => __DIR__ . '/credit-cards/argencard.png'],
|
||||
'cabal' => ['name' => 'Cabal', 'path' => __DIR__ . '/credit-cards/cabal.png'],
|
||||
'cencosud' => ['name' => 'Cencosud', 'path' => __DIR__ . '/credit-cards/cencosud.png'],
|
||||
'diners' => ['name' => 'Diners Club', 'path' => __DIR__ . '/credit-cards/diners.png'],
|
||||
'discover' => ['name' => 'Discover', 'path' => __DIR__ . '/credit-cards/discover.png'],
|
||||
'elo' => ['name' => 'Elo', 'path' => __DIR__ . '/credit-cards/elo.png'],
|
||||
'hipercard' => ['name' => 'Hipercard', 'path' => __DIR__ . '/credit-cards/hipercard.png'],
|
||||
'jcb' => ['name' => 'JCB', 'path' => __DIR__ . '/credit-cards/jcb.png'],
|
||||
'mastercard' => ['name' => 'Mastercard', 'path' => __DIR__ . '/credit-cards/mastercard.png'],
|
||||
'naranja' => ['name' => 'Naranja', 'path' => __DIR__ . '/credit-cards/naranja.png'],
|
||||
'targeta-shopping' => ['name' => 'Tarjeta Shopping', 'path' => __DIR__ . '/credit-cards/tarjeta-shopping.png'],
|
||||
'unionpay' => ['name' => 'Union Pay', 'path' => __DIR__ . '/credit-cards/unionpay.png'],
|
||||
'visa' => ['name' => 'Visa', 'path' => __DIR__ . '/credit-cards/visa.png'],
|
||||
'mir' => ['name' => 'MIR', 'path' => __DIR__ . '/credit-cards/mir.png'],
|
||||
'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png'],
|
||||
'rupay' => ['name' => 'Rupay', 'path' => __DIR__ . '/credit-cards/rupay.png']
|
||||
'amex' => __DIR__ . '/credit-cards/amex.png',
|
||||
'argencard' => __DIR__ . '/credit-cards/argencard.png',
|
||||
'cabal' => __DIR__ . '/credit-cards/cabal.png',
|
||||
'censosud' => __DIR__ . '/credit-cards/consosud.png',
|
||||
'diners' => __DIR__ . '/credit-cards/diners.png',
|
||||
'discover' => __DIR__ . '/credit-cards/discover.png',
|
||||
'elo' => __DIR__ . '/credit-cards/elo.png',
|
||||
'hipercard' => __DIR__ . '/credit-cards/hipercard.png',
|
||||
'jcb' => __DIR__ . '/credit-cards/jcb.png',
|
||||
'mastercard' => __DIR__ . '/credit-cards/mastercard.png',
|
||||
'naranja' => __DIR__ . '/credit-cards/naranja.png',
|
||||
'targeta-shopping' => __DIR__ . '/credit-cards/tarjeta-shopping.png',
|
||||
'union-china-pay' => __DIR__ . '/credit-cards/union-china-pay.png',
|
||||
'visa' => __DIR__ . '/credit-cards/visa.png',
|
||||
'mir' => __DIR__ . '/credit-cards/mir.png',
|
||||
'maestro' => __DIR__ . '/credit-cards/maestro.png',
|
||||
];
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
+194
-195
@@ -1,199 +1,198 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'af' => ['name' => 'Afghanistan', 'path' => __DIR__ . '/flags/af.png'],
|
||||
'ao' => ['name' => 'Angola', 'path' => __DIR__ . '/flags/ao.png'],
|
||||
'al' => ['name' => 'Albania', 'path' => __DIR__ . '/flags/al.png'],
|
||||
'ad' => ['name' => 'Andorra', 'path' => __DIR__ . '/flags/ad.png'],
|
||||
'ae' => ['name' => 'United Arab Emirates', 'path' => __DIR__ . '/flags/ae.png'],
|
||||
'ar' => ['name' => 'Argentina', 'path' => __DIR__ . '/flags/ar.png'],
|
||||
'am' => ['name' => 'Armenia', 'path' => __DIR__ . '/flags/am.png'],
|
||||
'ag' => ['name' => 'Antigua and Barbuda', 'path' => __DIR__ . '/flags/ag.png'],
|
||||
'au' => ['name' => 'Australia', 'path' => __DIR__ . '/flags/au.png'],
|
||||
'at' => ['name' => 'Austria', 'path' => __DIR__ . '/flags/at.png'],
|
||||
'az' => ['name' => 'Azerbaijan', 'path' => __DIR__ . '/flags/az.png'],
|
||||
'bi' => ['name' => 'Burundi', 'path' => __DIR__ . '/flags/bi.png'],
|
||||
'be' => ['name' => 'Belgium', 'path' => __DIR__ . '/flags/be.png'],
|
||||
'bj' => ['name' => 'Benin', 'path' => __DIR__ . '/flags/bj.png'],
|
||||
'bf' => ['name' => 'Burkina Faso', 'path' => __DIR__ . '/flags/bf.png'],
|
||||
'bd' => ['name' => 'Bangladesh', 'path' => __DIR__ . '/flags/bd.png'],
|
||||
'bg' => ['name' => 'Bulgaria', 'path' => __DIR__ . '/flags/bg.png'],
|
||||
'bh' => ['name' => 'Bahrain', 'path' => __DIR__ . '/flags/bh.png'],
|
||||
'bs' => ['name' => 'Bahamas', 'path' => __DIR__ . '/flags/bs.png'],
|
||||
'ba' => ['name' => 'Bosnia and Herzegovina', 'path' => __DIR__ . '/flags/ba.png'],
|
||||
'by' => ['name' => 'Belarus', 'path' => __DIR__ . '/flags/by.png'],
|
||||
'bz' => ['name' => 'Belize', 'path' => __DIR__ . '/flags/bz.png'],
|
||||
'bo' => ['name' => 'Bolivia', 'path' => __DIR__ . '/flags/bo.png'],
|
||||
'br' => ['name' => 'Brazil', 'path' => __DIR__ . '/flags/br.png'],
|
||||
'bb' => ['name' => 'Barbados', 'path' => __DIR__ . '/flags/bb.png'],
|
||||
'bn' => ['name' => 'Brunei Darussalam', 'path' => __DIR__ . '/flags/bn.png'],
|
||||
'bt' => ['name' => 'Bhutan', 'path' => __DIR__ . '/flags/bt.png'],
|
||||
'bw' => ['name' => 'Botswana', 'path' => __DIR__ . '/flags/bw.png'],
|
||||
'cf' => ['name' => 'Central African Republic', 'path' => __DIR__ . '/flags/cf.png'],
|
||||
'ca' => ['name' => 'Canada', 'path' => __DIR__ . '/flags/ca.png'],
|
||||
'ch' => ['name' => 'Switzerland', 'path' => __DIR__ . '/flags/ch.png'],
|
||||
'cl' => ['name' => 'Chile', 'path' => __DIR__ . '/flags/cl.png'],
|
||||
'cn' => ['name' => 'China', 'path' => __DIR__ . '/flags/cn.png'],
|
||||
'ci' => ['name' => 'Côte d\'Ivoire', 'path' => __DIR__ . '/flags/ci.png'],
|
||||
'cm' => ['name' => 'Cameroon', 'path' => __DIR__ . '/flags/cm.png'],
|
||||
'cd' => ['name' => 'Democratic Republic of the Congo', 'path' => __DIR__ . '/flags/cd.png'],
|
||||
'cg' => ['name' => 'Republic of the Congo', 'path' => __DIR__ . '/flags/cg.png'],
|
||||
'co' => ['name' => 'Colombia', 'path' => __DIR__ . '/flags/co.png'],
|
||||
'km' => ['name' => 'Comoros', 'path' => __DIR__ . '/flags/km.png'],
|
||||
'cv' => ['name' => 'Cape Verde', 'path' => __DIR__ . '/flags/cv.png'],
|
||||
'cr' => ['name' => 'Costa Rica', 'path' => __DIR__ . '/flags/cr.png'],
|
||||
'cu' => ['name' => 'Cuba', 'path' => __DIR__ . '/flags/cu.png'],
|
||||
'cy' => ['name' => 'Cyprus', 'path' => __DIR__ . '/flags/cy.png'],
|
||||
'cz' => ['name' => 'Czech Republic', 'path' => __DIR__ . '/flags/cz.png'],
|
||||
'de' => ['name' => 'Germany', 'path' => __DIR__ . '/flags/de.png'],
|
||||
'dj' => ['name' => 'Djibouti', 'path' => __DIR__ . '/flags/dj.png'],
|
||||
'dm' => ['name' => 'Dominica', 'path' => __DIR__ . '/flags/dm.png'],
|
||||
'dk' => ['name' => 'Denmark', 'path' => __DIR__ . '/flags/dk.png'],
|
||||
'do' => ['name' => 'Dominican Republic', 'path' => __DIR__ . '/flags/do.png'],
|
||||
'dz' => ['name' => 'Algeria', 'path' => __DIR__ . '/flags/dz.png'],
|
||||
'ec' => ['name' => 'Ecuador', 'path' => __DIR__ . '/flags/ec.png'],
|
||||
'eg' => ['name' => 'Egypt', 'path' => __DIR__ . '/flags/eg.png'],
|
||||
'er' => ['name' => 'Eritrea', 'path' => __DIR__ . '/flags/er.png'],
|
||||
'es' => ['name' => 'Spain', 'path' => __DIR__ . '/flags/es.png'],
|
||||
'ee' => ['name' => 'Estonia', 'path' => __DIR__ . '/flags/ee.png'],
|
||||
'et' => ['name' => 'Ethiopia', 'path' => __DIR__ . '/flags/et.png'],
|
||||
'fi' => ['name' => 'Finland', 'path' => __DIR__ . '/flags/fi.png'],
|
||||
'fj' => ['name' => 'Fiji', 'path' => __DIR__ . '/flags/fj.png'],
|
||||
'fr' => ['name' => 'France', 'path' => __DIR__ . '/flags/fr.png'],
|
||||
'fm' => ['name' => 'Micronesia (Federated States of)', 'path' => __DIR__ . '/flags/fm.png'],
|
||||
'ga' => ['name' => 'Gabon', 'path' => __DIR__ . '/flags/ga.png'],
|
||||
'gb' => ['name' => 'United Kingdom', 'path' => __DIR__ . '/flags/gb.png'],
|
||||
'ge' => ['name' => 'Georgia', 'path' => __DIR__ . '/flags/ge.png'],
|
||||
'gh' => ['name' => 'Ghana', 'path' => __DIR__ . '/flags/gh.png'],
|
||||
'gn' => ['name' => 'Guinea', 'path' => __DIR__ . '/flags/gn.png'],
|
||||
'gm' => ['name' => 'Gambia', 'path' => __DIR__ . '/flags/gm.png'],
|
||||
'gw' => ['name' => 'Guinea-Bissau', 'path' => __DIR__ . '/flags/gw.png'],
|
||||
'gq' => ['name' => 'Equatorial Guinea', 'path' => __DIR__ . '/flags/gq.png'],
|
||||
'gr' => ['name' => 'Greece', 'path' => __DIR__ . '/flags/gr.png'],
|
||||
'gd' => ['name' => 'Grenada', 'path' => __DIR__ . '/flags/gd.png'],
|
||||
'gt' => ['name' => 'Guatemala', 'path' => __DIR__ . '/flags/gt.png'],
|
||||
'gy' => ['name' => 'Guyana', 'path' => __DIR__ . '/flags/gy.png'],
|
||||
'hn' => ['name' => 'Honduras', 'path' => __DIR__ . '/flags/hn.png'],
|
||||
'hr' => ['name' => 'Croatia', 'path' => __DIR__ . '/flags/hr.png'],
|
||||
'ht' => ['name' => 'Haiti', 'path' => __DIR__ . '/flags/ht.png'],
|
||||
'hu' => ['name' => 'Hungary', 'path' => __DIR__ . '/flags/hu.png'],
|
||||
'id' => ['name' => 'Indonesia', 'path' => __DIR__ . '/flags/id.png'],
|
||||
'in' => ['name' => 'India', 'path' => __DIR__ . '/flags/in.png'],
|
||||
'ie' => ['name' => 'Ireland', 'path' => __DIR__ . '/flags/ie.png'],
|
||||
'ir' => ['name' => 'Iran (Islamic Republic of)', 'path' => __DIR__ . '/flags/ir.png'],
|
||||
'iq' => ['name' => 'Iraq', 'path' => __DIR__ . '/flags/iq.png'],
|
||||
'is' => ['name' => 'Iceland', 'path' => __DIR__ . '/flags/is.png'],
|
||||
'il' => ['name' => 'Israel', 'path' => __DIR__ . '/flags/il.png'],
|
||||
'it' => ['name' => 'Italy', 'path' => __DIR__ . '/flags/it.png'],
|
||||
'jm' => ['name' => 'Jamaica', 'path' => __DIR__ . '/flags/jm.png'],
|
||||
'jo' => ['name' => 'Jordan', 'path' => __DIR__ . '/flags/jo.png'],
|
||||
'jp' => ['name' => 'Japan', 'path' => __DIR__ . '/flags/jp.png'],
|
||||
'kz' => ['name' => 'Kazakhstan', 'path' => __DIR__ . '/flags/kz.png'],
|
||||
'ke' => ['name' => 'Kenya', 'path' => __DIR__ . '/flags/ke.png'],
|
||||
'kg' => ['name' => 'Kyrgyzstan', 'path' => __DIR__ . '/flags/kg.png'],
|
||||
'kh' => ['name' => 'Cambodia', 'path' => __DIR__ . '/flags/kh.png'],
|
||||
'ki' => ['name' => 'Kiribati', 'path' => __DIR__ . '/flags/ki.png'],
|
||||
'kn' => ['name' => 'Saint Kitts and Nevis', 'path' => __DIR__ . '/flags/kn.png'],
|
||||
'kr' => ['name' => 'South Korea', 'path' => __DIR__ . '/flags/kr.png'],
|
||||
'kw' => ['name' => 'Kuwait', 'path' => __DIR__ . '/flags/kw.png'],
|
||||
'la' => ['name' => 'Lao People\'s Democratic Republic', 'path' => __DIR__ . '/flags/la.png'],
|
||||
'lb' => ['name' => 'Lebanon', 'path' => __DIR__ . '/flags/lb.png'],
|
||||
'lr' => ['name' => 'Liberia', 'path' => __DIR__ . '/flags/lr.png'],
|
||||
'ly' => ['name' => 'Libya', 'path' => __DIR__ . '/flags/ly.png'],
|
||||
'lc' => ['name' => 'Saint Lucia', 'path' => __DIR__ . '/flags/lc.png'],
|
||||
'li' => ['name' => 'Liechtenstein', 'path' => __DIR__ . '/flags/li.png'],
|
||||
'lk' => ['name' => 'Sri Lanka', 'path' => __DIR__ . '/flags/lk.png'],
|
||||
'ls' => ['name' => 'Lesotho', 'path' => __DIR__ . '/flags/ls.png'],
|
||||
'lt' => ['name' => 'Lithuania', 'path' => __DIR__ . '/flags/lt.png'],
|
||||
'lu' => ['name' => 'Luxembourg', 'path' => __DIR__ . '/flags/lu.png'],
|
||||
'lv' => ['name' => 'Latvia', 'path' => __DIR__ . '/flags/lv.png'],
|
||||
'ma' => ['name' => 'Morocco', 'path' => __DIR__ . '/flags/ma.png'],
|
||||
'mc' => ['name' => 'Monaco', 'path' => __DIR__ . '/flags/mc.png'],
|
||||
'md' => ['name' => 'Moldova', 'path' => __DIR__ . '/flags/md.png'],
|
||||
'mg' => ['name' => 'Madagascar', 'path' => __DIR__ . '/flags/mg.png'],
|
||||
'mv' => ['name' => 'Maldives', 'path' => __DIR__ . '/flags/mv.png'],
|
||||
'mx' => ['name' => 'Mexico', 'path' => __DIR__ . '/flags/mx.png'],
|
||||
'mh' => ['name' => 'Marshall Islands', 'path' => __DIR__ . '/flags/mh.png'],
|
||||
'mk' => ['name' => 'North Macedonia', 'path' => __DIR__ . '/flags/mk.png'],
|
||||
'ml' => ['name' => 'Mali', 'path' => __DIR__ . '/flags/ml.png'],
|
||||
'mt' => ['name' => 'Malta', 'path' => __DIR__ . '/flags/mt.png'],
|
||||
'mm' => ['name' => 'Myanmar', 'path' => __DIR__ . '/flags/mm.png'],
|
||||
'me' => ['name' => 'Montenegro', 'path' => __DIR__ . '/flags/me.png'],
|
||||
'mn' => ['name' => 'Mongolia', 'path' => __DIR__ . '/flags/mn.png'],
|
||||
'mz' => ['name' => 'Mozambique', 'path' => __DIR__ . '/flags/mz.png'],
|
||||
'mr' => ['name' => 'Mauritania', 'path' => __DIR__ . '/flags/mr.png'],
|
||||
'mu' => ['name' => 'Mauritius', 'path' => __DIR__ . '/flags/mu.png'],
|
||||
'mw' => ['name' => 'Malawi', 'path' => __DIR__ . '/flags/mw.png'],
|
||||
'my' => ['name' => 'Malaysia', 'path' => __DIR__ . '/flags/my.png'],
|
||||
'na' => ['name' => 'Namibia', 'path' => __DIR__ . '/flags/na.png'],
|
||||
'ne' => ['name' => 'Niger', 'path' => __DIR__ . '/flags/ne.png'],
|
||||
'ng' => ['name' => 'Nigeria', 'path' => __DIR__ . '/flags/ng.png'],
|
||||
'ni' => ['name' => 'Nicaragua', 'path' => __DIR__ . '/flags/ni.png'],
|
||||
'nl' => ['name' => 'Netherlands', 'path' => __DIR__ . '/flags/nl.png'],
|
||||
'no' => ['name' => 'Norway', 'path' => __DIR__ . '/flags/no.png'],
|
||||
'np' => ['name' => 'Nepal', 'path' => __DIR__ . '/flags/np.png'],
|
||||
'nr' => ['name' => 'Nauru', 'path' => __DIR__ . '/flags/nr.png'],
|
||||
'nz' => ['name' => 'New Zealand', 'path' => __DIR__ . '/flags/nz.png'],
|
||||
'om' => ['name' => 'Oman', 'path' => __DIR__ . '/flags/om.png'],
|
||||
'pk' => ['name' => 'Pakistan', 'path' => __DIR__ . '/flags/pk.png'],
|
||||
'pa' => ['name' => 'Panama', 'path' => __DIR__ . '/flags/pa.png'],
|
||||
'pe' => ['name' => 'Peru', 'path' => __DIR__ . '/flags/pe.png'],
|
||||
'ph' => ['name' => 'Philippines', 'path' => __DIR__ . '/flags/ph.png'],
|
||||
'pw' => ['name' => 'Palau', 'path' => __DIR__ . '/flags/pw.png'],
|
||||
'pg' => ['name' => 'Papua New Guinea', 'path' => __DIR__ . '/flags/pg.png'],
|
||||
'pl' => ['name' => 'Poland', 'path' => __DIR__ . '/flags/pl.png'],
|
||||
'pf' => ['name' => 'French Polynesia', 'path' => __DIR__ . '/flags/pf.png'],
|
||||
'kp' => ['name' => 'North Korea', 'path' => __DIR__ . '/flags/kp.png'],
|
||||
'pt' => ['name' => 'Portugal', 'path' => __DIR__ . '/flags/pt.png'],
|
||||
'py' => ['name' => 'Paraguay', 'path' => __DIR__ . '/flags/py.png'],
|
||||
'qa' => ['name' => 'Qatar', 'path' => __DIR__ . '/flags/qa.png'],
|
||||
'ro' => ['name' => 'Romania', 'path' => __DIR__ . '/flags/ro.png'],
|
||||
'ru' => ['name' => 'Russia', 'path' => __DIR__ . '/flags/ru.png'],
|
||||
'rw' => ['name' => 'Rwanda', 'path' => __DIR__ . '/flags/rw.png'],
|
||||
'sa' => ['name' => 'Saudi Arabia', 'path' => __DIR__ . '/flags/sa.png'],
|
||||
'sd' => ['name' => 'Sudan', 'path' => __DIR__ . '/flags/sd.png'],
|
||||
'sn' => ['name' => 'Senegal', 'path' => __DIR__ . '/flags/sn.png'],
|
||||
'sg' => ['name' => 'Singapore', 'path' => __DIR__ . '/flags/sg.png'],
|
||||
'sb' => ['name' => 'Solomon Islands', 'path' => __DIR__ . '/flags/sb.png'],
|
||||
'sl' => ['name' => 'Sierra Leone', 'path' => __DIR__ . '/flags/sl.png'],
|
||||
'sv' => ['name' => 'El Salvador', 'path' => __DIR__ . '/flags/sv.png'],
|
||||
'sm' => ['name' => 'San Marino', 'path' => __DIR__ . '/flags/sm.png'],
|
||||
'so' => ['name' => 'Somalia', 'path' => __DIR__ . '/flags/so.png'],
|
||||
'rs' => ['name' => 'Serbia', 'path' => __DIR__ . '/flags/rs.png'],
|
||||
'ss' => ['name' => 'South Sudan', 'path' => __DIR__ . '/flags/ss.png'],
|
||||
'st' => ['name' => 'Sao Tome and Principe', 'path' => __DIR__ . '/flags/st.png'],
|
||||
'sr' => ['name' => 'Suriname', 'path' => __DIR__ . '/flags/sr.png'],
|
||||
'sk' => ['name' => 'Slovakia', 'path' => __DIR__ . '/flags/sk.png'],
|
||||
'si' => ['name' => 'Slovenia', 'path' => __DIR__ . '/flags/si.png'],
|
||||
'se' => ['name' => 'Sweden', 'path' => __DIR__ . '/flags/se.png'],
|
||||
'sz' => ['name' => 'Eswatini', 'path' => __DIR__ . '/flags/sz.png'],
|
||||
'sc' => ['name' => 'Seychelles', 'path' => __DIR__ . '/flags/sc.png'],
|
||||
'sy' => ['name' => 'Syria', 'path' => __DIR__ . '/flags/sy.png'],
|
||||
'td' => ['name' => 'Chad', 'path' => __DIR__ . '/flags/td.png'],
|
||||
'tg' => ['name' => 'Togo', 'path' => __DIR__ . '/flags/tg.png'],
|
||||
'th' => ['name' => 'Thailand', 'path' => __DIR__ . '/flags/th.png'],
|
||||
'tj' => ['name' => 'Tajikistan', 'path' => __DIR__ . '/flags/tj.png'],
|
||||
'tm' => ['name' => 'Turkmenistan', 'path' => __DIR__ . '/flags/tm.png'],
|
||||
'tl' => ['name' => 'Timor-Leste', 'path' => __DIR__ . '/flags/tl.png'],
|
||||
'to' => ['name' => 'Tonga', 'path' => __DIR__ . '/flags/to.png'],
|
||||
'tt' => ['name' => 'Trinidad and Tobago', 'path' => __DIR__ . '/flags/tt.png'],
|
||||
'tn' => ['name' => 'Tunisia', 'path' => __DIR__ . '/flags/tn.png'],
|
||||
'tr' => ['name' => 'Turkey', 'path' => __DIR__ . '/flags/tr.png'],
|
||||
'tv' => ['name' => 'Tuvalu', 'path' => __DIR__ . '/flags/tv.png'],
|
||||
'tz' => ['name' => 'Tanzania', 'path' => __DIR__ . '/flags/tz.png'],
|
||||
'ug' => ['name' => 'Uganda', 'path' => __DIR__ . '/flags/ug.png'],
|
||||
'ua' => ['name' => 'Ukraine', 'path' => __DIR__ . '/flags/ua.png'],
|
||||
'uy' => ['name' => 'Uruguay', 'path' => __DIR__ . '/flags/uy.png'],
|
||||
'us' => ['name' => 'United States', 'path' => __DIR__ . '/flags/us.png'],
|
||||
'uz' => ['name' => 'Uzbekistan', 'path' => __DIR__ . '/flags/uz.png'],
|
||||
'va' => ['name' => 'Vatican City', 'path' => __DIR__ . '/flags/va.png'],
|
||||
'vc' => ['name' => 'Saint Vincent and the Grenadines', 'path' => __DIR__ . '/flags/vc.png'],
|
||||
've' => ['name' => 'Venezuela', 'path' => __DIR__ . '/flags/ve.png'],
|
||||
'vn' => ['name' => 'Vietnam', 'path' => __DIR__ . '/flags/vn.png'],
|
||||
'vu' => ['name' => 'Vanuatu', 'path' => __DIR__ . '/flags/vu.png'],
|
||||
'ws' => ['name' => 'Samoa', 'path' => __DIR__ . '/flags/ws.png'],
|
||||
'ye' => ['name' => 'Yemen', 'path' => __DIR__ . '/flags/ye.png'],
|
||||
'za' => ['name' => 'South Africa', 'path' => __DIR__ . '/flags/za.png'],
|
||||
'zm' => ['name' => 'Zambia', 'path' => __DIR__ . '/flags/zm.png'],
|
||||
'zw' => ['name' => 'Zimbabwe', 'path' => __DIR__ . '/flags/zw.png'],
|
||||
'af' => __DIR__ . '/flags/af.png',
|
||||
'ao' => __DIR__ . '/flags/ao.png',
|
||||
'al' => __DIR__ . '/flags/al.png',
|
||||
'ad' => __DIR__ . '/flags/ad.png',
|
||||
'ae' => __DIR__ . '/flags/ae.png',
|
||||
'ar' => __DIR__ . '/flags/ar.png',
|
||||
'am' => __DIR__ . '/flags/am.png',
|
||||
'ag' => __DIR__ . '/flags/ag.png',
|
||||
'au' => __DIR__ . '/flags/au.png',
|
||||
'at' => __DIR__ . '/flags/at.png',
|
||||
'az' => __DIR__ . '/flags/az.png',
|
||||
'bi' => __DIR__ . '/flags/bi.png',
|
||||
'be' => __DIR__ . '/flags/be.png',
|
||||
'bj' => __DIR__ . '/flags/bj.png',
|
||||
'bf' => __DIR__ . '/flags/bf.png',
|
||||
'bd' => __DIR__ . '/flags/bd.png',
|
||||
'bg' => __DIR__ . '/flags/bg.png',
|
||||
'bh' => __DIR__ . '/flags/bh.png',
|
||||
'bs' => __DIR__ . '/flags/bs.png',
|
||||
'ba' => __DIR__ . '/flags/ba.png',
|
||||
'by' => __DIR__ . '/flags/by.png',
|
||||
'bz' => __DIR__ . '/flags/bz.png',
|
||||
'bo' => __DIR__ . '/flags/bo.png',
|
||||
'br' => __DIR__ . '/flags/br.png',
|
||||
'bb' => __DIR__ . '/flags/bb.png',
|
||||
'bn' => __DIR__ . '/flags/bn.png',
|
||||
'bt' => __DIR__ . '/flags/bt.png',
|
||||
'bw' => __DIR__ . '/flags/bw.png',
|
||||
'cf' => __DIR__ . '/flags/cf.png',
|
||||
'ca' => __DIR__ . '/flags/ca.png',
|
||||
'ch' => __DIR__ . '/flags/ch.png',
|
||||
'cl' => __DIR__ . '/flags/cl.png',
|
||||
'cn' => __DIR__ . '/flags/cn.png',
|
||||
'ci' => __DIR__ . '/flags/ci.png',
|
||||
'cm' => __DIR__ . '/flags/cm.png',
|
||||
'cd' => __DIR__ . '/flags/cd.png',
|
||||
'cg' => __DIR__ . '/flags/cg.png',
|
||||
'co' => __DIR__ . '/flags/co.png',
|
||||
'km' => __DIR__ . '/flags/km.png',
|
||||
'cv' => __DIR__ . '/flags/cv.png',
|
||||
'cr' => __DIR__ . '/flags/cr.png',
|
||||
'cu' => __DIR__ . '/flags/cu.png',
|
||||
'cy' => __DIR__ . '/flags/cy.png',
|
||||
'cz' => __DIR__ . '/flags/cz.png',
|
||||
'de' => __DIR__ . '/flags/de.png',
|
||||
'dj' => __DIR__ . '/flags/dj.png',
|
||||
'dm' => __DIR__ . '/flags/dm.png',
|
||||
'dk' => __DIR__ . '/flags/dk.png',
|
||||
'do' => __DIR__ . '/flags/do.png',
|
||||
'dz' => __DIR__ . '/flags/dz.png',
|
||||
'ec' => __DIR__ . '/flags/ec.png',
|
||||
'eg' => __DIR__ . '/flags/eg.png',
|
||||
'er' => __DIR__ . '/flags/er.png',
|
||||
'es' => __DIR__ . '/flags/es.png',
|
||||
'ee' => __DIR__ . '/flags/ee.png',
|
||||
'et' => __DIR__ . '/flags/et.png',
|
||||
'fi' => __DIR__ . '/flags/fi.png',
|
||||
'fj' => __DIR__ . '/flags/fj.png',
|
||||
'fr' => __DIR__ . '/flags/fr.png',
|
||||
'fm' => __DIR__ . '/flags/fm.png',
|
||||
'ga' => __DIR__ . '/flags/ga.png',
|
||||
'gb' => __DIR__ . '/flags/gb.png',
|
||||
'ge' => __DIR__ . '/flags/ge.png',
|
||||
'gh' => __DIR__ . '/flags/gh.png',
|
||||
'gn' => __DIR__ . '/flags/gn.png',
|
||||
'gm' => __DIR__ . '/flags/gm.png',
|
||||
'gw' => __DIR__ . '/flags/gw.png',
|
||||
'gq' => __DIR__ . '/flags/gq.png',
|
||||
'gr' => __DIR__ . '/flags/gr.png',
|
||||
'gd' => __DIR__ . '/flags/gd.png',
|
||||
'gt' => __DIR__ . '/flags/gt.png',
|
||||
'gy' => __DIR__ . '/flags/gy.png',
|
||||
'hn' => __DIR__ . '/flags/hn.png',
|
||||
'hr' => __DIR__ . '/flags/hr.png',
|
||||
'ht' => __DIR__ . '/flags/ht.png',
|
||||
'hu' => __DIR__ . '/flags/hu.png',
|
||||
'id' => __DIR__ . '/flags/id.png',
|
||||
'in' => __DIR__ . '/flags/in.png',
|
||||
'ie' => __DIR__ . '/flags/ie.png',
|
||||
'ir' => __DIR__ . '/flags/ir.png',
|
||||
'iq' => __DIR__ . '/flags/iq.png',
|
||||
'is' => __DIR__ . '/flags/is.png',
|
||||
'il' => __DIR__ . '/flags/il.png',
|
||||
'it' => __DIR__ . '/flags/it.png',
|
||||
'jm' => __DIR__ . '/flags/jm.png',
|
||||
'jo' => __DIR__ . '/flags/jo.png',
|
||||
'jp' => __DIR__ . '/flags/jp.png',
|
||||
'kz' => __DIR__ . '/flags/kz.png',
|
||||
'ke' => __DIR__ . '/flags/ke.png',
|
||||
'kg' => __DIR__ . '/flags/kg.png',
|
||||
'kh' => __DIR__ . '/flags/kh.png',
|
||||
'ki' => __DIR__ . '/flags/ki.png',
|
||||
'kn' => __DIR__ . '/flags/kn.png',
|
||||
'kr' => __DIR__ . '/flags/kr.png',
|
||||
'kw' => __DIR__ . '/flags/kw.png',
|
||||
'la' => __DIR__ . '/flags/la.png',
|
||||
'lb' => __DIR__ . '/flags/lb.png',
|
||||
'lr' => __DIR__ . '/flags/lr.png',
|
||||
'ly' => __DIR__ . '/flags/ly.png',
|
||||
'lc' => __DIR__ . '/flags/lc.png',
|
||||
'li' => __DIR__ . '/flags/li.png',
|
||||
'lk' => __DIR__ . '/flags/lk.png',
|
||||
'ls' => __DIR__ . '/flags/ls.png',
|
||||
'lt' => __DIR__ . '/flags/ls.png',
|
||||
'lu' => __DIR__ . '/flags/lu.png',
|
||||
'lv' => __DIR__ . '/flags/lv.png',
|
||||
'ma' => __DIR__ . '/flags/ma.png',
|
||||
'mc' => __DIR__ . '/flags/mc.png',
|
||||
'md' => __DIR__ . '/flags/md.png',
|
||||
'mg' => __DIR__ . '/flags/mg.png',
|
||||
'mv' => __DIR__ . '/flags/mv.png',
|
||||
'mx' => __DIR__ . '/flags/mx.png',
|
||||
'mh' => __DIR__ . '/flags/mh.png',
|
||||
'mk' => __DIR__ . '/flags/mk.png',
|
||||
'ml' => __DIR__ . '/flags/ml.png',
|
||||
'mt' => __DIR__ . '/flags/mt.png',
|
||||
'mm' => __DIR__ . '/flags/mm.png',
|
||||
'me' => __DIR__ . '/flags/me.png',
|
||||
'mn' => __DIR__ . '/flags/mn.png',
|
||||
'mz' => __DIR__ . '/flags/mz.png',
|
||||
'mr' => __DIR__ . '/flags/mr.png',
|
||||
'mu' => __DIR__ . '/flags/mu.png',
|
||||
'mw' => __DIR__ . '/flags/mw.png',
|
||||
'my' => __DIR__ . '/flags/my.png',
|
||||
'na' => __DIR__ . '/flags/na.png',
|
||||
'ne' => __DIR__ . '/flags/ne.png',
|
||||
'ng' => __DIR__ . '/flags/ng.png',
|
||||
'ni' => __DIR__ . '/flags/ni.png',
|
||||
'nl' => __DIR__ . '/flags/nl.png',
|
||||
'no' => __DIR__ . '/flags/no.png',
|
||||
'np' => __DIR__ . '/flags/np.png',
|
||||
'nr' => __DIR__ . '/flags/nr.png',
|
||||
'nz' => __DIR__ . '/flags/nz.png',
|
||||
'om' => __DIR__ . '/flags/om.png',
|
||||
'pk' => __DIR__ . '/flags/pk.png',
|
||||
'pa' => __DIR__ . '/flags/pa.png',
|
||||
'pe' => __DIR__ . '/flags/pe.png',
|
||||
'ph' => __DIR__ . '/flags/ph.png',
|
||||
'pw' => __DIR__ . '/flags/pw.png',
|
||||
'pg' => __DIR__ . '/flags/pg.png',
|
||||
'pl' => __DIR__ . '/flags/pl.png',
|
||||
'kp' => __DIR__ . '/flags/kp.png',
|
||||
'pt' => __DIR__ . '/flags/pt.png',
|
||||
'py' => __DIR__ . '/flags/py.png',
|
||||
'qa' => __DIR__ . '/flags/qa.png',
|
||||
'ro' => __DIR__ . '/flags/ro.png',
|
||||
'ru' => __DIR__ . '/flags/ru.png',
|
||||
'rw' => __DIR__ . '/flags/rw.png',
|
||||
'sa' => __DIR__ . '/flags/sa.png',
|
||||
'sd' => __DIR__ . '/flags/sd.png',
|
||||
'sn' => __DIR__ . '/flags/sn.png',
|
||||
'sg' => __DIR__ . '/flags/sg.png',
|
||||
'sb' => __DIR__ . '/flags/sb.png',
|
||||
'sl' => __DIR__ . '/flags/sl.png',
|
||||
'sv' => __DIR__ . '/flags/sv.png',
|
||||
'sm' => __DIR__ . '/flags/sm.png',
|
||||
'so' => __DIR__ . '/flags/so.png',
|
||||
'rs' => __DIR__ . '/flags/rs.png',
|
||||
'ss' => __DIR__ . '/flags/ss.png',
|
||||
'st' => __DIR__ . '/flags/st.png',
|
||||
'sr' => __DIR__ . '/flags/sr.png',
|
||||
'sk' => __DIR__ . '/flags/sk.png',
|
||||
'si' => __DIR__ . '/flags/si.png',
|
||||
'se' => __DIR__ . '/flags/se.png',
|
||||
'sz' => __DIR__ . '/flags/sz.png',
|
||||
'sc' => __DIR__ . '/flags/sc.png',
|
||||
'sy' => __DIR__ . '/flags/sy.png',
|
||||
'td' => __DIR__ . '/flags/td.png',
|
||||
'tg' => __DIR__ . '/flags/tg.png',
|
||||
'th' => __DIR__ . '/flags/th.png',
|
||||
'tj' => __DIR__ . '/flags/tj.png',
|
||||
'tm' => __DIR__ . '/flags/tm.png',
|
||||
'tl' => __DIR__ . '/flags/tl.png',
|
||||
'to' => __DIR__ . '/flags/to.png',
|
||||
'tt' => __DIR__ . '/flags/tt.png',
|
||||
'tn' => __DIR__ . '/flags/tn.png',
|
||||
'tr' => __DIR__ . '/flags/tr.png',
|
||||
'tv' => __DIR__ . '/flags/tv.png',
|
||||
'tz' => __DIR__ . '/flags/tz.png',
|
||||
'ug' => __DIR__ . '/flags/ug.png',
|
||||
'ua' => __DIR__ . '/flags/ua.png',
|
||||
'uy' => __DIR__ . '/flags/uy.png',
|
||||
'us' => __DIR__ . '/flags/us.png',
|
||||
'uz' => __DIR__ . '/flags/uz.png',
|
||||
'va' => __DIR__ . '/flags/va.png',
|
||||
'vc' => __DIR__ . '/flags/vc.png',
|
||||
've' => __DIR__ . '/flags/ve.png',
|
||||
'vn' => __DIR__ . '/flags/vn.png',
|
||||
'vu' => __DIR__ . '/flags/vu.png',
|
||||
'ws' => __DIR__ . '/flags/ws.png',
|
||||
'ye' => __DIR__ . '/flags/ye.png',
|
||||
'za' => __DIR__ . '/flags/za.png',
|
||||
'zm' => __DIR__ . '/flags/zm.png',
|
||||
'zw' => __DIR__ . '/flags/zw.png',
|
||||
];
|
||||
|
||||
+3518
-17
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
|
||||
return [
|
||||
'collections' => [
|
||||
'$collection' => ID::custom('databases'),
|
||||
'$id' => ID::custom('collections'),
|
||||
'name' => 'Collections',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => ID::custom('databaseInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('databaseId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'signed' => true,
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'format' => '',
|
||||
'filters' => [],
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('name'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
'signed' => true,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('enabled'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'signed' => true,
|
||||
'size' => 0,
|
||||
'format' => '',
|
||||
'filters' => [],
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('documentSecurity'),
|
||||
'type' => Database::VAR_BOOLEAN,
|
||||
'signed' => true,
|
||||
'size' => 0,
|
||||
'format' => '',
|
||||
'filters' => [],
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('attributes'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'size' => 1000000,
|
||||
'required' => false,
|
||||
'signed' => true,
|
||||
'array' => false,
|
||||
'filters' => ['subQueryAttributes'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('indexes'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'size' => 1000000,
|
||||
'required' => false,
|
||||
'signed' => true,
|
||||
'array' => false,
|
||||
'filters' => ['subQueryIndexes'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('search'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_fulltext_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['search'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_name'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['name'],
|
||||
'lengths' => [256],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_enabled'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['enabled'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_documentSecurity'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['documentSecurity'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
],
|
||||
]
|
||||
];
|
||||
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
|
||||
$logsCollection = [];
|
||||
|
||||
$logsCollection['stats'] = [
|
||||
'$collection' => ID::custom(Database::METADATA),
|
||||
'$id' => ID::custom('stats'),
|
||||
'name' => 'stats',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => ID::custom('metric'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('region'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('value'),
|
||||
'type' => Database::VAR_INTEGER,
|
||||
'format' => '',
|
||||
'size' => 8,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('time'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => false,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('period'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 4,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_key_time'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['time'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_DESC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_period_time'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['period', 'time'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_metric_period_time'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['metric', 'period', 'time'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_DESC],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $logsCollection;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Initializes console project document.
|
||||
*/
|
||||
|
||||
use Appwrite\Network\Platform;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\System\System;
|
||||
|
||||
$console = [
|
||||
'$id' => ID::custom('console'),
|
||||
'$sequence' => ID::custom('console'),
|
||||
'name' => 'Appwrite',
|
||||
'$collection' => ID::custom('projects'),
|
||||
'description' => 'Appwrite core engine',
|
||||
'logo' => '',
|
||||
'teamId' => null,
|
||||
'webhooks' => [],
|
||||
'keys' => [],
|
||||
'platforms' => [
|
||||
[
|
||||
'$collection' => ID::custom('platforms'),
|
||||
'name' => 'Localhost',
|
||||
'type' => Platform::TYPE_WEB,
|
||||
'hostname' => 'localhost',
|
||||
], // Current host is added on app init
|
||||
],
|
||||
'region' => 'fra',
|
||||
'legalName' => '',
|
||||
'legalCountry' => '',
|
||||
'legalState' => '',
|
||||
'legalCity' => '',
|
||||
'legalAddress' => '',
|
||||
'legalTaxId' => '',
|
||||
'auths' => [
|
||||
'mockNumbers' => [],
|
||||
'invites' => System::getEnv('_APP_CONSOLE_INVITES', 'enabled') === 'enabled',
|
||||
'limit' => (System::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user
|
||||
'duration' => TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds
|
||||
'sessionAlerts' => System::getEnv('_APP_CONSOLE_SESSION_ALERTS', 'disabled') === 'enabled',
|
||||
'invalidateSessions' => true
|
||||
],
|
||||
'authWhitelistEmails' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [],
|
||||
'authWhitelistIPs' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [],
|
||||
'oAuthProviders' => [
|
||||
'githubEnabled' => true,
|
||||
'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''),
|
||||
'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '')
|
||||
],
|
||||
'smtpBaseTemplate' => APP_BRANDED_EMAIL_BASE_TEMPLATE,
|
||||
];
|
||||
|
||||
return $console;
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CORS Configuration
|
||||
*
|
||||
* Centralised list of allowed methods, headers, and exposed headers for CORS responses.
|
||||
*/
|
||||
return [
|
||||
'allowedMethods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
'allowedHeaders' => [
|
||||
'Accept',
|
||||
'Origin',
|
||||
'Cookie',
|
||||
'Set-Cookie',
|
||||
// Content
|
||||
'Content-Type',
|
||||
'Content-Range',
|
||||
// Appwrite
|
||||
'X-Appwrite-Project',
|
||||
'X-Appwrite-Key',
|
||||
'X-Appwrite-Dev-Key',
|
||||
'X-Appwrite-Locale',
|
||||
'X-Appwrite-Mode',
|
||||
'X-Appwrite-JWT',
|
||||
'X-Appwrite-Response-Format',
|
||||
'X-Appwrite-Timeout',
|
||||
'X-Appwrite-ID',
|
||||
'X-Appwrite-Timestamp',
|
||||
'X-Appwrite-Session',
|
||||
'X-Appwrite-Platform',
|
||||
// SDK generator
|
||||
'X-SDK-Version',
|
||||
'X-SDK-Name',
|
||||
'X-SDK-Language',
|
||||
'X-SDK-Platform',
|
||||
'X-SDK-GraphQL',
|
||||
'X-SDK-Profile',
|
||||
// Caching
|
||||
'Range',
|
||||
'Cache-Control',
|
||||
'Expires',
|
||||
'Pragma',
|
||||
// Server to server
|
||||
'X-Fallback-Cookies',
|
||||
'X-Requested-With',
|
||||
'X-Forwarded-For',
|
||||
'X-Forwarded-User-Agent',
|
||||
],
|
||||
'exposedHeaders' => [
|
||||
'X-Appwrite-Session',
|
||||
'X-Fallback-Cookies',
|
||||
],
|
||||
];
|
||||
+56
-870
File diff suppressed because it is too large
Load Diff
+13
-206
@@ -44,28 +44,6 @@ return [
|
||||
'$description' => 'This event triggers when a verification token for a user is validated.'
|
||||
],
|
||||
],
|
||||
'targets' => [
|
||||
'$model' => Response::MODEL_TARGET,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any user\'s target event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a user\'s target is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a user\'s target is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a user\'s target is deleted.',
|
||||
],
|
||||
],
|
||||
'tokens' => [
|
||||
'$model' => Response::MODEL_TOKEN,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any user\'s token event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a user\'s token is created.',
|
||||
],
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a user is created.'
|
||||
],
|
||||
@@ -95,65 +73,6 @@ return [
|
||||
'$model' => Response::MODEL_DATABASE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any database event.',
|
||||
'tables' => [
|
||||
'$model' => Response::MODEL_TABLE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any table event.',
|
||||
'rows' => [
|
||||
'$model' => Response::MODEL_ROW,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any rows event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a row is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a row is updated.'
|
||||
],
|
||||
'upsert' => [
|
||||
'$description' => 'This event triggers when a document is upserted.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a row is deleted.'
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'$model' => Response::MODEL_COLUMN_INDEX,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any indexes event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an index is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when an index is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an index is deleted.'
|
||||
]
|
||||
],
|
||||
'columns' => [
|
||||
'$model' => Response::MODEL_COLUMN,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any columns event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a column is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an column is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a column is created.',
|
||||
],
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a table is created.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a table is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a table is deleted.',
|
||||
],
|
||||
],
|
||||
'collections' => [
|
||||
'$model' => Response::MODEL_COLLECTION,
|
||||
'$resource' => true,
|
||||
@@ -165,15 +84,12 @@ return [
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a document is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a document is updated.'
|
||||
],
|
||||
'upsert' => [
|
||||
'$description' => 'This event triggers when a document is upserted.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a document is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a document is updated.'
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'$model' => Response::MODEL_INDEX,
|
||||
@@ -184,10 +100,7 @@ return [
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an index is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a column is created.',
|
||||
],
|
||||
]
|
||||
],
|
||||
'attributes' => [
|
||||
'$model' => Response::MODEL_ATTRIBUTE,
|
||||
@@ -196,9 +109,6 @@ return [
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an attribute is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a column is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an attribute is deleted.'
|
||||
]
|
||||
@@ -206,22 +116,22 @@ return [
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a collection is created.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a collection is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a collection is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a collection is updated.',
|
||||
]
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a database is created.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a database is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a database is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a database is updated.',
|
||||
]
|
||||
],
|
||||
'buckets' => [
|
||||
'$model' => Response::MODEL_BUCKET,
|
||||
@@ -273,44 +183,13 @@ return [
|
||||
],
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a team is created.'
|
||||
'$description' => 'This event triggers when a bucket is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a team is deleted.',
|
||||
'$description' => 'This event triggers when a bucket is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a team is updated.',
|
||||
'prefs' => [
|
||||
'$description' => 'This event triggers when a team\'s preferences are updated.',
|
||||
],
|
||||
]
|
||||
],
|
||||
'sites' => [
|
||||
'$model' => Response::MODEL_SITE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any sites event.',
|
||||
'deployments' => [
|
||||
'$model' => Response::MODEL_DEPLOYMENT,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any deployments event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a deployment is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a deployment is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a deployment is updated.'
|
||||
],
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a site is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a site is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a site is updated.',
|
||||
'$description' => 'This event triggers when a bucket is updated.',
|
||||
]
|
||||
],
|
||||
'functions' => [
|
||||
@@ -354,77 +233,5 @@ return [
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a function is updated.',
|
||||
]
|
||||
],
|
||||
'messages' => [
|
||||
'$model' => Response::MODEL_MESSAGE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any messaging event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a message is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a message is updated.',
|
||||
],
|
||||
],
|
||||
'topics' => [
|
||||
'$model' => Response::MODEL_TOPIC,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any topic event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a topic is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a topic is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a topic is deleted.'
|
||||
],
|
||||
'subscribers' => [
|
||||
'$model' => Response::MODEL_SUBSCRIBER,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any subscriber event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a subscriber is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a subscriber is deleted.'
|
||||
],
|
||||
],
|
||||
],
|
||||
'providers' => [
|
||||
'$model' => Response::MODEL_PROVIDER,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any provider event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a provider is created.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a provider is updated.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a provider is deleted.'
|
||||
],
|
||||
],
|
||||
'schedules' => [
|
||||
'$model' => Response::MODEL_SCHEDULE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any schedule event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a schedule is created.',
|
||||
],
|
||||
],
|
||||
'rules' => [
|
||||
'$model' => Response::MODEL_PROXY_RULE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any proxy rule event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a proxy rule is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a proxy rule is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a proxy rule is updated.',
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* List of Appwrite Sites supported frameworks
|
||||
*/
|
||||
|
||||
use Utopia\Config\Config;
|
||||
|
||||
$templateRuntimes = Config::getParam('template-runtimes');
|
||||
|
||||
return [
|
||||
'analog' => [
|
||||
'key' => 'analog',
|
||||
'name' => 'Analog',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/analog/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/analog/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/analog',
|
||||
'startCommand' => 'bash helpers/analog/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/analog/public',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'angular' => [
|
||||
'key' => 'angular',
|
||||
'name' => 'Angular',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/angular/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/angular/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/angular',
|
||||
'startCommand' => 'bash helpers/angular/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/angular/browser',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.csr.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'nextjs' => [
|
||||
'key' => 'nextjs',
|
||||
'name' => 'Next.js',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/next-js/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './.next',
|
||||
'startCommand' => 'bash helpers/next-js/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './out',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'react' => [
|
||||
'key' => 'react',
|
||||
'name' => 'React',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'nuxt' => [
|
||||
'key' => 'nuxt',
|
||||
'name' => 'Nuxt',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/nuxt/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './.output',
|
||||
'startCommand' => 'bash helpers/nuxt/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run generate',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './output/public',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'vue' => [
|
||||
'key' => 'vue',
|
||||
'name' => 'Vue.js',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'sveltekit' => [
|
||||
'key' => 'sveltekit',
|
||||
'name' => 'SvelteKit',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/sveltekit/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/sveltekit/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'astro' => [
|
||||
'key' => 'astro',
|
||||
'name' => 'Astro',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/astro/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/astro/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/astro/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'tanstack-start' => [
|
||||
'key' => 'tanstack-start',
|
||||
'name' => 'TanStack Start',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/tanstack-start/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/tanstack-start/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './.output',
|
||||
'startCommand' => 'bash helpers/tanstack-start/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/client',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'remix' => [
|
||||
'key' => 'remix',
|
||||
'name' => 'Remix',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/remix/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/remix/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/remix/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build/client',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'lynx' => [
|
||||
'key' => 'lynx',
|
||||
'name' => 'Lynx',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'flutter' => [
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'flutter-3.35',
|
||||
'runtimes' => $templateRuntimes['FLUTTER'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'flutter build web --release -t lib/main.dart',
|
||||
'installCommand' => 'flutter pub get',
|
||||
'outputDirectory' => './build/web',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
],
|
||||
],
|
||||
],
|
||||
'react-native' => [
|
||||
'key' => 'react-native',
|
||||
'name' => 'React Native',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'vite' => [
|
||||
'key' => 'vite',
|
||||
'name' => 'Vite',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
],
|
||||
]
|
||||
],
|
||||
'other' => [
|
||||
'key' => 'other',
|
||||
'name' => 'Other',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => $templateRuntimes['NODE'],
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => '',
|
||||
'installCommand' => '',
|
||||
'outputDirectory' => './',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
+72
-533
@@ -1,537 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ISO 639-1 standard language codes
|
||||
* https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||
*
|
||||
* Source:
|
||||
* https://www.andiamo.co.uk/resources/iso-language-codes/
|
||||
*
|
||||
*/
|
||||
|
||||
return [
|
||||
[
|
||||
"code" => "af",
|
||||
"name" => "Afrikaans",
|
||||
],
|
||||
[
|
||||
"code" => "ar-ae",
|
||||
"name" => "Arabic (U.A.E.)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-bh",
|
||||
"name" => "Arabic (Bahrain)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-dz",
|
||||
"name" => "Arabic (Algeria)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-eg",
|
||||
"name" => "Arabic (Egypt)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-iq",
|
||||
"name" => "Arabic (Iraq)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-jo",
|
||||
"name" => "Arabic (Jordan)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-kw",
|
||||
"name" => "Arabic (Kuwait)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-lb",
|
||||
"name" => "Arabic (Lebanon)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-ly",
|
||||
"name" => "Arabic (Libya)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-ma",
|
||||
"name" => "Arabic (Morocco)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-om",
|
||||
"name" => "Arabic (Oman)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-qa",
|
||||
"name" => "Arabic (Qatar)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-sa",
|
||||
"name" => "Arabic (Saudi Arabia)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-sy",
|
||||
"name" => "Arabic (Syria)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-tn",
|
||||
"name" => "Arabic (Tunisia)",
|
||||
],
|
||||
[
|
||||
"code" => "ar-ye",
|
||||
"name" => "Arabic (Yemen)",
|
||||
],
|
||||
[
|
||||
"code" => "as",
|
||||
"name" => "Assamese",
|
||||
],
|
||||
[
|
||||
"code" => "az",
|
||||
"name" => "Azerbaijani",
|
||||
],
|
||||
[
|
||||
"code" => "be",
|
||||
"name" => "Belarusian",
|
||||
],
|
||||
[
|
||||
"code" => "bg",
|
||||
"name" => "Bulgarian",
|
||||
],
|
||||
[
|
||||
"code" => "bh",
|
||||
"name" => "Bihari",
|
||||
],
|
||||
[
|
||||
"code" => "bn",
|
||||
"name" => "Bengali",
|
||||
],
|
||||
[
|
||||
"code" => "bs",
|
||||
"name" => "Bosnian",
|
||||
],
|
||||
[
|
||||
"code" => "ca",
|
||||
"name" => "Catalan",
|
||||
],
|
||||
[
|
||||
"code" => "cs",
|
||||
"name" => "Czech",
|
||||
],
|
||||
[
|
||||
"code" => "cy",
|
||||
"name" => "Welsh",
|
||||
],
|
||||
[
|
||||
"code" => "da",
|
||||
"name" => "Danish",
|
||||
],
|
||||
[
|
||||
"code" => "de",
|
||||
"name" => "German (Standard)",
|
||||
],
|
||||
[
|
||||
"code" => "de-at",
|
||||
"name" => "German (Austria)",
|
||||
],
|
||||
[
|
||||
"code" => "de-ch",
|
||||
"name" => "German (Switzerland)",
|
||||
],
|
||||
[
|
||||
"code" => "de-li",
|
||||
"name" => "German (Liechtenstein)",
|
||||
],
|
||||
[
|
||||
"code" => "de-lu",
|
||||
"name" => "German (Luxembourg)",
|
||||
],
|
||||
[
|
||||
"code" => "el",
|
||||
"name" => "Greek",
|
||||
],
|
||||
[
|
||||
"code" => "en",
|
||||
"name" => "English",
|
||||
],
|
||||
[
|
||||
"code" => "en-au",
|
||||
"name" => "English (Australia)",
|
||||
],
|
||||
[
|
||||
"code" => "en-bz",
|
||||
"name" => "English (Belize)",
|
||||
],
|
||||
[
|
||||
"code" => "en-ca",
|
||||
"name" => "English (Canada)",
|
||||
],
|
||||
[
|
||||
"code" => "en-gb",
|
||||
"name" => "English (United Kingdom)",
|
||||
],
|
||||
[
|
||||
"code" => "en-ie",
|
||||
"name" => "English (Ireland)",
|
||||
],
|
||||
[
|
||||
"code" => "en-jm",
|
||||
"name" => "English (Jamaica)",
|
||||
],
|
||||
[
|
||||
"code" => "en-nz",
|
||||
"name" => "English (New Zealand)",
|
||||
],
|
||||
[
|
||||
"code" => "en-tt",
|
||||
"name" => "English (Trinidad)",
|
||||
],
|
||||
[
|
||||
"code" => "en-us",
|
||||
"name" => "English (United States)",
|
||||
],
|
||||
[
|
||||
"code" => "en-za",
|
||||
"name" => "English (South Africa)",
|
||||
],
|
||||
[
|
||||
"code" => "eo",
|
||||
"name" => "Esperanto",
|
||||
],
|
||||
[
|
||||
"code" => "es",
|
||||
"name" => "Spanish (Spain)",
|
||||
],
|
||||
[
|
||||
"code" => "es-ar",
|
||||
"name" => "Spanish (Argentina)",
|
||||
],
|
||||
[
|
||||
"code" => "es-bo",
|
||||
"name" => "Spanish (Bolivia)",
|
||||
],
|
||||
[
|
||||
"code" => "es-cl",
|
||||
"name" => "Spanish (Chile)",
|
||||
],
|
||||
[
|
||||
"code" => "es-co",
|
||||
"name" => "Spanish (Colombia)",
|
||||
],
|
||||
[
|
||||
"code" => "es-cr",
|
||||
"name" => "Spanish (Costa Rica)",
|
||||
],
|
||||
[
|
||||
"code" => "es-do",
|
||||
"name" => "Spanish (Dominican Republic)",
|
||||
],
|
||||
[
|
||||
"code" => "es-ec",
|
||||
"name" => "Spanish (Ecuador)",
|
||||
],
|
||||
[
|
||||
"code" => "es-gt",
|
||||
"name" => "Spanish (Guatemala)",
|
||||
],
|
||||
[
|
||||
"code" => "es-hn",
|
||||
"name" => "Spanish (Honduras)",
|
||||
],
|
||||
[
|
||||
"code" => "es-mx",
|
||||
"name" => "Spanish (Mexico)",
|
||||
],
|
||||
[
|
||||
"code" => "es-ni",
|
||||
"name" => "Spanish (Nicaragua)",
|
||||
],
|
||||
[
|
||||
"code" => "es-pa",
|
||||
"name" => "Spanish (Panama)",
|
||||
],
|
||||
[
|
||||
"code" => "es-pe",
|
||||
"name" => "Spanish (Peru)",
|
||||
],
|
||||
[
|
||||
"code" => "es-pr",
|
||||
"name" => "Spanish (Puerto Rico)",
|
||||
],
|
||||
[
|
||||
"code" => "es-py",
|
||||
"name" => "Spanish (Paraguay)",
|
||||
],
|
||||
[
|
||||
"code" => "es-sv",
|
||||
"name" => "Spanish (El Salvador)",
|
||||
],
|
||||
[
|
||||
"code" => "es-uy",
|
||||
"name" => "Spanish (Uruguay)",
|
||||
],
|
||||
[
|
||||
"code" => "es-ve",
|
||||
"name" => "Spanish (Venezuela)",
|
||||
],
|
||||
[
|
||||
"code" => "et",
|
||||
"name" => "Estonian",
|
||||
],
|
||||
[
|
||||
"code" => "eu",
|
||||
"name" => "Basque",
|
||||
],
|
||||
[
|
||||
"code" => "fa",
|
||||
"name" => "Farsi",
|
||||
],
|
||||
[
|
||||
"code" => "fi",
|
||||
"name" => "Finnish",
|
||||
],
|
||||
[
|
||||
"code" => "fo",
|
||||
"name" => "Faeroese",
|
||||
],
|
||||
[
|
||||
"code" => "fr",
|
||||
"name" => "French (Standard)",
|
||||
],
|
||||
[
|
||||
"code" => "fr-be",
|
||||
"name" => "French (Belgium)",
|
||||
],
|
||||
[
|
||||
"code" => "fr-ca",
|
||||
"name" => "French (Canada)",
|
||||
],
|
||||
[
|
||||
"code" => "fr-ch",
|
||||
"name" => "French (Switzerland)",
|
||||
],
|
||||
[
|
||||
"code" => "fr-lu",
|
||||
"name" => "French (Luxembourg)",
|
||||
],
|
||||
[
|
||||
"code" => "ga",
|
||||
"name" => "Irish",
|
||||
],
|
||||
[
|
||||
"code" => "gd",
|
||||
"name" => "Gaelic (Scotland)",
|
||||
],
|
||||
[
|
||||
"code" => "he",
|
||||
"name" => "Hebrew",
|
||||
],
|
||||
[
|
||||
"code" => "hi",
|
||||
"name" => "Hindi",
|
||||
],
|
||||
[
|
||||
"code" => "hr",
|
||||
"name" => "Croatian",
|
||||
],
|
||||
[
|
||||
"code" => "hu",
|
||||
"name" => "Hungarian",
|
||||
],
|
||||
[
|
||||
"code" => "id",
|
||||
"name" => "Indonesian",
|
||||
],
|
||||
[
|
||||
"code" => "is",
|
||||
"name" => "Icelandic",
|
||||
],
|
||||
[
|
||||
"code" => "it",
|
||||
"name" => "Italian (Standard)",
|
||||
],
|
||||
[
|
||||
"code" => "it-ch",
|
||||
"name" => "Italian (Switzerland)",
|
||||
],
|
||||
[
|
||||
"code" => "ja",
|
||||
"name" => "Japanese",
|
||||
],
|
||||
[
|
||||
"code" => "ji",
|
||||
"name" => "Yiddish",
|
||||
],
|
||||
[
|
||||
"code" => "ko",
|
||||
"name" => "Korean",
|
||||
],
|
||||
[
|
||||
"code" => "ku",
|
||||
"name" => "Kurdish",
|
||||
],
|
||||
[
|
||||
"code" => "lt",
|
||||
"name" => "Lithuanian",
|
||||
],
|
||||
[
|
||||
"code" => "lv",
|
||||
"name" => "Latvian",
|
||||
],
|
||||
[
|
||||
"code" => "mk",
|
||||
"name" => "Macedonian (FYROM)",
|
||||
],
|
||||
[
|
||||
"code" => "ml",
|
||||
"name" => "Malayalam",
|
||||
],
|
||||
[
|
||||
"code" => "ms",
|
||||
"name" => "Malaysian",
|
||||
],
|
||||
[
|
||||
"code" => "mt",
|
||||
"name" => "Maltese",
|
||||
],
|
||||
[
|
||||
"code" => "nb",
|
||||
"name" => "Norwegian (Bokmål)",
|
||||
],
|
||||
[
|
||||
"code" => "ne",
|
||||
"name" => "Nepali",
|
||||
],
|
||||
[
|
||||
"code" => "nl",
|
||||
"name" => "Dutch (Standard)",
|
||||
],
|
||||
[
|
||||
"code" => "nl-be",
|
||||
"name" => "Dutch (Belgium)",
|
||||
],
|
||||
[
|
||||
"code" => "nn",
|
||||
"name" => "Norwegian (Nynorsk)",
|
||||
],
|
||||
[
|
||||
"code" => "no",
|
||||
"name" => "Norwegian",
|
||||
],
|
||||
[
|
||||
"code" => "pa",
|
||||
"name" => "Punjabi",
|
||||
],
|
||||
[
|
||||
"code" => "pl",
|
||||
"name" => "Polish",
|
||||
],
|
||||
[
|
||||
"code" => "pt",
|
||||
"name" => "Portuguese (Portugal)",
|
||||
],
|
||||
[
|
||||
"code" => "pt-br",
|
||||
"name" => "Portuguese (Brazil)",
|
||||
],
|
||||
[
|
||||
"code" => "rm",
|
||||
"name" => "Rhaeto-Romanic",
|
||||
],
|
||||
[
|
||||
"code" => "ro",
|
||||
"name" => "Romanian",
|
||||
],
|
||||
[
|
||||
"code" => "ro-md",
|
||||
"name" => "Romanian (Republic of Moldova)",
|
||||
],
|
||||
[
|
||||
"code" => "ru",
|
||||
"name" => "Russian",
|
||||
],
|
||||
[
|
||||
"code" => "ru-md",
|
||||
"name" => "Russian (Republic of Moldova)",
|
||||
],
|
||||
[
|
||||
"code" => "sb",
|
||||
"name" => "Sorbian",
|
||||
],
|
||||
[
|
||||
"code" => "sk",
|
||||
"name" => "Slovak",
|
||||
],
|
||||
[
|
||||
"code" => "sl",
|
||||
"name" => "Slovenian",
|
||||
],
|
||||
[
|
||||
"code" => "sq",
|
||||
"name" => "Albanian",
|
||||
],
|
||||
[
|
||||
"code" => "sr",
|
||||
"name" => "Serbian",
|
||||
],
|
||||
[
|
||||
"code" => "sv",
|
||||
"name" => "Swedish",
|
||||
],
|
||||
[
|
||||
"code" => "sv-fi",
|
||||
"name" => "Swedish (Finland)",
|
||||
],
|
||||
[
|
||||
"code" => "th",
|
||||
"name" => "Thai",
|
||||
],
|
||||
[
|
||||
"code" => "tn",
|
||||
"name" => "Tswana",
|
||||
],
|
||||
[
|
||||
"code" => "tr",
|
||||
"name" => "Turkish",
|
||||
],
|
||||
[
|
||||
"code" => "ts",
|
||||
"name" => "Tsonga",
|
||||
],
|
||||
[
|
||||
"code" => "ua",
|
||||
"name" => "Ukrainian",
|
||||
],
|
||||
[
|
||||
"code" => "ur",
|
||||
"name" => "Urdu",
|
||||
],
|
||||
[
|
||||
"code" => "ve",
|
||||
"name" => "Venda",
|
||||
],
|
||||
[
|
||||
"code" => "vi",
|
||||
"name" => "Vietnamese",
|
||||
],
|
||||
[
|
||||
"code" => "xh",
|
||||
"name" => "Xhosa",
|
||||
],
|
||||
[
|
||||
"code" => "zh-cn",
|
||||
"name" => "Chinese (PRC)",
|
||||
],
|
||||
[
|
||||
"code" => "zh-hk",
|
||||
"name" => "Chinese (Hong Kong)",
|
||||
],
|
||||
[
|
||||
"code" => "zh-sg",
|
||||
"name" => "Chinese (Singapore)",
|
||||
],
|
||||
[
|
||||
"code" => "zh-tw",
|
||||
"name" => "Chinese (Taiwan)",
|
||||
],
|
||||
[
|
||||
"code" => "zu",
|
||||
"name" => "Zulu",
|
||||
],
|
||||
'af', // Afrikaans
|
||||
'ar', // Arabic
|
||||
'as', // Assamese
|
||||
'az', // Azerbaijani
|
||||
'be', // Belarusian
|
||||
'bg', // Bulgarian
|
||||
'bh', // Bihari
|
||||
'bn', // Bengali
|
||||
'bs', // Bosnian
|
||||
'ca', // Catalan
|
||||
'cs', // Czech
|
||||
'da', // Danish
|
||||
'de', // German
|
||||
'en', // English
|
||||
'eo', // Esperanto
|
||||
'es', // Spanish
|
||||
'fa', // Farsi/Persian
|
||||
'fi', // Finnish
|
||||
'fo', // Faroese
|
||||
'fr', // French
|
||||
'el', // Greek
|
||||
'ga', // Irish
|
||||
'gu', // Gujrati
|
||||
'he', // Hebrew
|
||||
'hi', // Hindi,
|
||||
'hr', // Croatian
|
||||
'hu', // Hungarian
|
||||
'hy', // Armenian
|
||||
'id', // Indonesian
|
||||
'is', // Icelandic
|
||||
'it', // Italian
|
||||
'ja', // Japanese
|
||||
'jv', // Javanese
|
||||
'kn', // Kannada
|
||||
'km', // Khmer
|
||||
'ko', // Korean
|
||||
'la', // Latin
|
||||
'lb', // Luxembourgish
|
||||
'lt', // Lithuanian
|
||||
'lv', // Latvian
|
||||
'ml', // Malayalam
|
||||
'mr', // Marathi
|
||||
'ms', // Malay
|
||||
'nb', // Norwegian bokmål
|
||||
'nl', // Dutch
|
||||
'nn', // Norwegian nynorsk
|
||||
'ne', // Nepali
|
||||
'or', // Oriya
|
||||
'tl', // Filipino
|
||||
'pl', // Polish
|
||||
'pt-br', // Portuguese - Brazil
|
||||
'pt-pt', // Portuguese - Portugal
|
||||
'pa', // Punjabi
|
||||
'ro', // Romanian
|
||||
'ru', // Russian
|
||||
'sa', //Sanskrit
|
||||
'sd', // Sindhi
|
||||
'si', // Sinhala
|
||||
'sk', // Slovakia
|
||||
'sl', // Slovenian
|
||||
'sn', // Shona
|
||||
'sq', // Albanian
|
||||
'sv', // Swedish
|
||||
'ta', // Tamil
|
||||
'te', // Telugu
|
||||
'th', // Thai
|
||||
'tr', // Turkish
|
||||
'uk', // Ukrainian
|
||||
'ur', // Urdu
|
||||
'vi', // Vietnamese
|
||||
'zh-cn', // Chinese - China
|
||||
'zh-tw', // Chinese - Taiwan
|
||||
];
|
||||
|
||||
@@ -1,46 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Continent codes with names and approximate central coordinates
|
||||
*
|
||||
* Coordinates represent approximate geographical centers of each continent
|
||||
* Note: These are simplified centroids and may not represent the exact geographical center
|
||||
*/
|
||||
|
||||
return [
|
||||
'AF' => [
|
||||
'name' => 'Africa',
|
||||
'latitude' => 8.7832,
|
||||
'longitude' => 34.5085
|
||||
],
|
||||
'AN' => [
|
||||
'name' => 'Antarctica',
|
||||
'latitude' => -82.8628,
|
||||
'longitude' => 135.0000
|
||||
],
|
||||
'AS' => [
|
||||
'name' => 'Asia',
|
||||
'latitude' => 34.0479,
|
||||
'longitude' => 100.6197
|
||||
],
|
||||
'EU' => [
|
||||
'name' => 'Europe',
|
||||
'latitude' => 54.5260,
|
||||
'longitude' => 15.2551
|
||||
],
|
||||
'NA' => [
|
||||
'name' => 'North America',
|
||||
'latitude' => 54.5260,
|
||||
'longitude' => -105.2551
|
||||
],
|
||||
'OC' => [
|
||||
'name' => 'Oceania',
|
||||
'latitude' => -22.7359,
|
||||
'longitude' => 140.0188
|
||||
],
|
||||
'SA' => [
|
||||
'name' => 'South America',
|
||||
'latitude' => -8.7832,
|
||||
'longitude' => -55.4915
|
||||
],
|
||||
'AF',
|
||||
'AN',
|
||||
'AS',
|
||||
'EU',
|
||||
'NA',
|
||||
'OC',
|
||||
'SA',
|
||||
];
|
||||
|
||||
+194
-206
@@ -1,210 +1,198 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ISO 3166 standard country codes with country names and coordinates
|
||||
* https://www.iso.org/iso-3166-country-codes.html
|
||||
*
|
||||
* Source:
|
||||
* https://www.iso.org/obp/ui/#search/code/
|
||||
* Coordinates source: Natural Earth Data (approximate country centroids)
|
||||
*/
|
||||
|
||||
return [
|
||||
'AF' => ['name' => 'Afghanistan', 'latitude' => 33.0, 'longitude' => 66.0],
|
||||
'AO' => ['name' => 'Angola', 'latitude' => -12.5, 'longitude' => 18.5],
|
||||
'AL' => ['name' => 'Albania', 'latitude' => 41.0, 'longitude' => 20.0],
|
||||
'AD' => ['name' => 'Andorra', 'latitude' => 42.5, 'longitude' => 1.6],
|
||||
'AE' => ['name' => 'United Arab Emirates', 'latitude' => 24.0, 'longitude' => 54.0],
|
||||
'AR' => ['name' => 'Argentina', 'latitude' => -34.0, 'longitude' => -64.0],
|
||||
'AM' => ['name' => 'Armenia', 'latitude' => 40.0, 'longitude' => 45.0],
|
||||
'AG' => ['name' => 'Antigua and Barbuda', 'latitude' => 17.05, 'longitude' => -61.8],
|
||||
'AU' => ['name' => 'Australia', 'latitude' => -25.0, 'longitude' => 135.0],
|
||||
'AT' => ['name' => 'Austria', 'latitude' => 47.3, 'longitude' => 13.3],
|
||||
'AZ' => ['name' => 'Azerbaijan', 'latitude' => 40.5, 'longitude' => 47.5],
|
||||
'BI' => ['name' => 'Burundi', 'latitude' => -3.5, 'longitude' => 30.0],
|
||||
'BE' => ['name' => 'Belgium', 'latitude' => 50.8, 'longitude' => 4.0],
|
||||
'BJ' => ['name' => 'Benin', 'latitude' => 9.5, 'longitude' => 2.25],
|
||||
'BF' => ['name' => 'Burkina Faso', 'latitude' => 13.0, 'longitude' => -2.0],
|
||||
'BD' => ['name' => 'Bangladesh', 'latitude' => 24.0, 'longitude' => 90.0],
|
||||
'BG' => ['name' => 'Bulgaria', 'latitude' => 43.0, 'longitude' => 25.0],
|
||||
'BH' => ['name' => 'Bahrain', 'latitude' => 26.0, 'longitude' => 50.5],
|
||||
'BS' => ['name' => 'Bahamas', 'latitude' => 24.25, 'longitude' => -76.0],
|
||||
'BA' => ['name' => 'Bosnia and Herzegovina', 'latitude' => 44.0, 'longitude' => 18.0],
|
||||
'BY' => ['name' => 'Belarus', 'latitude' => 53.0, 'longitude' => 28.0],
|
||||
'BZ' => ['name' => 'Belize', 'latitude' => 17.25, 'longitude' => -88.75],
|
||||
'BO' => ['name' => 'Bolivia', 'latitude' => -17.0, 'longitude' => -65.0],
|
||||
'BR' => ['name' => 'Brazil', 'latitude' => -10.0, 'longitude' => -55.0],
|
||||
'BB' => ['name' => 'Barbados', 'latitude' => 13.17, 'longitude' => -59.53],
|
||||
'BN' => ['name' => 'Brunei', 'latitude' => 4.5, 'longitude' => 114.67],
|
||||
'BT' => ['name' => 'Bhutan', 'latitude' => 27.5, 'longitude' => 90.5],
|
||||
'BW' => ['name' => 'Botswana', 'latitude' => -22.0, 'longitude' => 24.0],
|
||||
'CF' => ['name' => 'Central African Republic', 'latitude' => 7.0, 'longitude' => 21.0],
|
||||
'CA' => ['name' => 'Canada', 'latitude' => 60.0, 'longitude' => -95.0],
|
||||
'CH' => ['name' => 'Switzerland', 'latitude' => 47.0, 'longitude' => 8.0],
|
||||
'CL' => ['name' => 'Chile', 'latitude' => -30.0, 'longitude' => -71.0],
|
||||
'CN' => ['name' => 'China', 'latitude' => 35.0, 'longitude' => 105.0],
|
||||
'CI' => ['name' => 'Côte d\'Ivoire', 'latitude' => 8.0, 'longitude' => -5.0],
|
||||
'CM' => ['name' => 'Cameroon', 'latitude' => 6.0, 'longitude' => 12.0],
|
||||
'CD' => ['name' => 'Democratic Republic of the Congo', 'latitude' => -2.5, 'longitude' => 23.5],
|
||||
'CG' => ['name' => 'Republic of the Congo', 'latitude' => -1.0, 'longitude' => 15.0],
|
||||
'CO' => ['name' => 'Colombia', 'latitude' => 4.0, 'longitude' => -72.0],
|
||||
'KM' => ['name' => 'Comoros', 'latitude' => -12.17, 'longitude' => 44.25],
|
||||
'CV' => ['name' => 'Cape Verde', 'latitude' => 16.0, 'longitude' => -24.0],
|
||||
'CR' => ['name' => 'Costa Rica', 'latitude' => 10.0, 'longitude' => -84.0],
|
||||
'CU' => ['name' => 'Cuba', 'latitude' => 21.5, 'longitude' => -80.0],
|
||||
'CY' => ['name' => 'Cyprus', 'latitude' => 35.0, 'longitude' => 33.0],
|
||||
'CZ' => ['name' => 'Czech Republic', 'latitude' => 49.75, 'longitude' => 15.5],
|
||||
'DE' => ['name' => 'Germany', 'latitude' => 51.0, 'longitude' => 9.0],
|
||||
'DJ' => ['name' => 'Djibouti', 'latitude' => 11.5, 'longitude' => 43.0],
|
||||
'DM' => ['name' => 'Dominica', 'latitude' => 15.42, 'longitude' => -61.33],
|
||||
'DK' => ['name' => 'Denmark', 'latitude' => 56.0, 'longitude' => 10.0],
|
||||
'DO' => ['name' => 'Dominican Republic', 'latitude' => 19.0, 'longitude' => -70.67],
|
||||
'DZ' => ['name' => 'Algeria', 'latitude' => 28.0, 'longitude' => 3.0],
|
||||
'EC' => ['name' => 'Ecuador', 'latitude' => -2.0, 'longitude' => -77.5],
|
||||
'EG' => ['name' => 'Egypt', 'latitude' => 27.0, 'longitude' => 30.0],
|
||||
'ER' => ['name' => 'Eritrea', 'latitude' => 15.0, 'longitude' => 39.0],
|
||||
'ES' => ['name' => 'Spain', 'latitude' => 40.0, 'longitude' => -4.0],
|
||||
'EE' => ['name' => 'Estonia', 'latitude' => 59.0, 'longitude' => 26.0],
|
||||
'ET' => ['name' => 'Ethiopia', 'latitude' => 8.0, 'longitude' => 38.0],
|
||||
'FI' => ['name' => 'Finland', 'latitude' => 64.0, 'longitude' => 26.0],
|
||||
'FJ' => ['name' => 'Fiji', 'latitude' => -18.0, 'longitude' => 175.0],
|
||||
'FR' => ['name' => 'France', 'latitude' => 46.0, 'longitude' => 2.0],
|
||||
'FM' => ['name' => 'Micronesia', 'latitude' => 6.92, 'longitude' => 158.25],
|
||||
'GA' => ['name' => 'Gabon', 'latitude' => -1.0, 'longitude' => 11.75],
|
||||
'GB' => ['name' => 'United Kingdom', 'latitude' => 54.0, 'longitude' => -2.0],
|
||||
'GE' => ['name' => 'Georgia', 'latitude' => 42.0, 'longitude' => 43.5],
|
||||
'GH' => ['name' => 'Ghana', 'latitude' => 8.0, 'longitude' => -2.0],
|
||||
'GN' => ['name' => 'Guinea', 'latitude' => 11.0, 'longitude' => -10.0],
|
||||
'GM' => ['name' => 'Gambia', 'latitude' => 13.47, 'longitude' => -16.57],
|
||||
'GW' => ['name' => 'Guinea-Bissau', 'latitude' => 12.0, 'longitude' => -15.0],
|
||||
'GQ' => ['name' => 'Equatorial Guinea', 'latitude' => 2.0, 'longitude' => 10.0],
|
||||
'GR' => ['name' => 'Greece', 'latitude' => 39.0, 'longitude' => 22.0],
|
||||
'GD' => ['name' => 'Grenada', 'latitude' => 12.12, 'longitude' => -61.67],
|
||||
'GT' => ['name' => 'Guatemala', 'latitude' => 15.5, 'longitude' => -90.25],
|
||||
'GY' => ['name' => 'Guyana', 'latitude' => 5.0, 'longitude' => -59.0],
|
||||
'HK' => ['name' => 'Hong Kong', 'latitude' => 22.25, 'longitude' => 114.17],
|
||||
'HN' => ['name' => 'Honduras', 'latitude' => 15.0, 'longitude' => -86.5],
|
||||
'HR' => ['name' => 'Croatia', 'latitude' => 45.17, 'longitude' => 15.5],
|
||||
'HT' => ['name' => 'Haiti', 'latitude' => 19.0, 'longitude' => -72.42],
|
||||
'HU' => ['name' => 'Hungary', 'latitude' => 47.0, 'longitude' => 20.0],
|
||||
'ID' => ['name' => 'Indonesia', 'latitude' => -5.0, 'longitude' => 120.0],
|
||||
'IN' => ['name' => 'India', 'latitude' => 20.0, 'longitude' => 77.0],
|
||||
'IE' => ['name' => 'Ireland', 'latitude' => 53.0, 'longitude' => -8.0],
|
||||
'IR' => ['name' => 'Iran', 'latitude' => 32.0, 'longitude' => 53.0],
|
||||
'IQ' => ['name' => 'Iraq', 'latitude' => 33.0, 'longitude' => 44.0],
|
||||
'IS' => ['name' => 'Iceland', 'latitude' => 65.0, 'longitude' => -18.0],
|
||||
'IL' => ['name' => 'Israel', 'latitude' => 31.5, 'longitude' => 34.75],
|
||||
'IT' => ['name' => 'Italy', 'latitude' => 42.83, 'longitude' => 12.83],
|
||||
'JM' => ['name' => 'Jamaica', 'latitude' => 18.25, 'longitude' => -77.5],
|
||||
'JO' => ['name' => 'Jordan', 'latitude' => 31.0, 'longitude' => 36.0],
|
||||
'JP' => ['name' => 'Japan', 'latitude' => 36.0, 'longitude' => 138.0],
|
||||
'KZ' => ['name' => 'Kazakhstan', 'latitude' => 48.0, 'longitude' => 68.0],
|
||||
'KE' => ['name' => 'Kenya', 'latitude' => 1.0, 'longitude' => 38.0],
|
||||
'KG' => ['name' => 'Kyrgyzstan', 'latitude' => 41.0, 'longitude' => 75.0],
|
||||
'KH' => ['name' => 'Cambodia', 'latitude' => 13.0, 'longitude' => 105.0],
|
||||
'KI' => ['name' => 'Kiribati', 'latitude' => 1.42, 'longitude' => 173.0],
|
||||
'KN' => ['name' => 'Saint Kitts and Nevis', 'latitude' => 17.33, 'longitude' => -62.75],
|
||||
'KR' => ['name' => 'South Korea', 'latitude' => 37.0, 'longitude' => 127.5],
|
||||
'KW' => ['name' => 'Kuwait', 'latitude' => 29.34, 'longitude' => 47.66],
|
||||
'LA' => ['name' => 'Laos', 'latitude' => 18.0, 'longitude' => 105.0],
|
||||
'LB' => ['name' => 'Lebanon', 'latitude' => 33.83, 'longitude' => 35.83],
|
||||
'LR' => ['name' => 'Liberia', 'latitude' => 6.5, 'longitude' => -9.5],
|
||||
'LY' => ['name' => 'Libya', 'latitude' => 25.0, 'longitude' => 17.0],
|
||||
'LC' => ['name' => 'Saint Lucia', 'latitude' => 13.88, 'longitude' => -61.13],
|
||||
'LI' => ['name' => 'Liechtenstein', 'latitude' => 47.17, 'longitude' => 9.53],
|
||||
'LK' => ['name' => 'Sri Lanka', 'latitude' => 7.0, 'longitude' => 81.0],
|
||||
'LS' => ['name' => 'Lesotho', 'latitude' => -29.5, 'longitude' => 28.5],
|
||||
'LT' => ['name' => 'Lithuania', 'latitude' => 56.0, 'longitude' => 24.0],
|
||||
'LU' => ['name' => 'Luxembourg', 'latitude' => 49.75, 'longitude' => 6.17],
|
||||
'LV' => ['name' => 'latitudevia', 'latitude' => 57.0, 'longitude' => 25.0],
|
||||
'MA' => ['name' => 'Morocco', 'latitude' => 32.0, 'longitude' => -5.0],
|
||||
'MC' => ['name' => 'Monaco', 'latitude' => 43.73, 'longitude' => 7.4],
|
||||
'MD' => ['name' => 'Moldova', 'latitude' => 47.0, 'longitude' => 29.0],
|
||||
'MG' => ['name' => 'Madagascar', 'latitude' => -20.0, 'longitude' => 47.0],
|
||||
'MV' => ['name' => 'Maldives', 'latitude' => 3.25, 'longitude' => 73.0],
|
||||
'MX' => ['name' => 'Mexico', 'latitude' => 23.0, 'longitude' => -102.0],
|
||||
'MH' => ['name' => 'Marshall Islands', 'latitude' => 9.0, 'longitude' => 168.0],
|
||||
'MK' => ['name' => 'North Macedonia', 'latitude' => 41.83, 'longitude' => 22.0],
|
||||
'ML' => ['name' => 'Mali', 'latitude' => 17.0, 'longitude' => -4.0],
|
||||
'MT' => ['name' => 'Malta', 'latitude' => 35.83, 'longitude' => 14.58],
|
||||
'MM' => ['name' => 'Myanmar', 'latitude' => 22.0, 'longitude' => 98.0],
|
||||
'ME' => ['name' => 'Montenegro', 'latitude' => 42.5, 'longitude' => 19.3],
|
||||
'MN' => ['name' => 'Mongolia', 'latitude' => 46.0, 'longitude' => 105.0],
|
||||
'MZ' => ['name' => 'Mozambique', 'latitude' => -18.25, 'longitude' => 35.0],
|
||||
'MR' => ['name' => 'Mauritania', 'latitude' => 20.0, 'longitude' => -12.0],
|
||||
'MU' => ['name' => 'Mauritius', 'latitude' => -20.28, 'longitude' => 57.55],
|
||||
'MW' => ['name' => 'Malawi', 'latitude' => -13.5, 'longitude' => 34.0],
|
||||
'MY' => ['name' => 'Malaysia', 'latitude' => 2.5, 'longitude' => 112.5],
|
||||
'NA' => ['name' => 'Namibia', 'latitude' => -22.0, 'longitude' => 17.0],
|
||||
'NE' => ['name' => 'Niger', 'latitude' => 16.0, 'longitude' => 8.0],
|
||||
'NG' => ['name' => 'Nigeria', 'latitude' => 10.0, 'longitude' => 8.0],
|
||||
'NI' => ['name' => 'Nicaragua', 'latitude' => 13.0, 'longitude' => -85.0],
|
||||
'NL' => ['name' => 'Netherlands', 'latitude' => 52.5, 'longitude' => 5.75],
|
||||
'NO' => ['name' => 'Norway', 'latitude' => 62.0, 'longitude' => 10.0],
|
||||
'NP' => ['name' => 'Nepal', 'latitude' => 28.0, 'longitude' => 84.0],
|
||||
'NR' => ['name' => 'Nauru', 'latitude' => -0.53, 'longitude' => 166.92],
|
||||
'NZ' => ['name' => 'New Zealand', 'latitude' => -41.0, 'longitude' => 174.0],
|
||||
'OM' => ['name' => 'Oman', 'latitude' => 21.0, 'longitude' => 57.0],
|
||||
'PK' => ['name' => 'Pakistan', 'latitude' => 30.0, 'longitude' => 70.0],
|
||||
'PS' => ['name' => 'Palestine', 'latitude' => 31.9, 'longitude' => 35.2],
|
||||
'PA' => ['name' => 'Panama', 'latitude' => 9.0, 'longitude' => -80.0],
|
||||
'PE' => ['name' => 'Peru', 'latitude' => -10.0, 'longitude' => -76.0],
|
||||
'PH' => ['name' => 'Philippines', 'latitude' => 13.0, 'longitude' => 122.0],
|
||||
'PW' => ['name' => 'Palau', 'latitude' => 7.5, 'longitude' => 134.5],
|
||||
'PG' => ['name' => 'Papua New Guinea', 'latitude' => -6.0, 'longitude' => 147.0],
|
||||
'PL' => ['name' => 'Poland', 'latitude' => 52.0, 'longitude' => 20.0],
|
||||
'KP' => ['name' => 'North Korea', 'latitude' => 40.0, 'longitude' => 127.0],
|
||||
'PT' => ['name' => 'Portugal', 'latitude' => 39.5, 'longitude' => -8.0],
|
||||
'PY' => ['name' => 'Paraguay', 'latitude' => -23.0, 'longitude' => -58.0],
|
||||
'QA' => ['name' => 'Qatar', 'latitude' => 25.5, 'longitude' => 51.25],
|
||||
'RO' => ['name' => 'Romania', 'latitude' => 46.0, 'longitude' => 25.0],
|
||||
'RU' => ['name' => 'Russia', 'latitude' => 60.0, 'longitude' => 100.0],
|
||||
'RW' => ['name' => 'Rwanda', 'latitude' => -2.0, 'longitude' => 30.0],
|
||||
'SA' => ['name' => 'Saudi Arabia', 'latitude' => 25.0, 'longitude' => 45.0],
|
||||
'SD' => ['name' => 'Sudan', 'latitude' => 15.0, 'longitude' => 30.0],
|
||||
'SN' => ['name' => 'Senegal', 'latitude' => 14.0, 'longitude' => -14.0],
|
||||
'SG' => ['name' => 'Singapore', 'latitude' => 1.37, 'longitude' => 103.8],
|
||||
'SB' => ['name' => 'Solomon Islands', 'latitude' => -8.0, 'longitude' => 159.0],
|
||||
'SL' => ['name' => 'Sierra Leone', 'latitude' => 8.5, 'longitude' => -11.5],
|
||||
'SV' => ['name' => 'El Salvador', 'latitude' => 13.83, 'longitude' => -88.92],
|
||||
'SM' => ['name' => 'San Marino', 'latitude' => 43.77, 'longitude' => 12.42],
|
||||
'SO' => ['name' => 'Somalia', 'latitude' => 10.0, 'longitude' => 49.0],
|
||||
'RS' => ['name' => 'Serbia', 'latitude' => 44.0, 'longitude' => 21.0],
|
||||
'SS' => ['name' => 'South Sudan', 'latitude' => 8.0, 'longitude' => 30.0],
|
||||
'ST' => ['name' => 'São Tomé and Príncipe', 'latitude' => 1.0, 'longitude' => 7.0],
|
||||
'SR' => ['name' => 'Suriname', 'latitude' => 4.0, 'longitude' => -56.0],
|
||||
'SK' => ['name' => 'Slovakia', 'latitude' => 48.67, 'longitude' => 19.5],
|
||||
'SI' => ['name' => 'Slovenia', 'latitude' => 46.0, 'longitude' => 15.0],
|
||||
'SE' => ['name' => 'Sweden', 'latitude' => 62.0, 'longitude' => 15.0],
|
||||
'SZ' => ['name' => 'Eswatini', 'latitude' => -26.5, 'longitude' => 31.5],
|
||||
'SC' => ['name' => 'Seychelles', 'latitude' => -4.58, 'longitude' => 55.67],
|
||||
'SY' => ['name' => 'Syria', 'latitude' => 35.0, 'longitude' => 38.0],
|
||||
'TD' => ['name' => 'Chad', 'latitude' => 15.0, 'longitude' => 19.0],
|
||||
'TG' => ['name' => 'Togo', 'latitude' => 8.0, 'longitude' => 1.17],
|
||||
'TH' => ['name' => 'Thailand', 'latitude' => 15.0, 'longitude' => 100.0],
|
||||
'TJ' => ['name' => 'Tajikistan', 'latitude' => 39.0, 'longitude' => 71.0],
|
||||
'TM' => ['name' => 'Turkmenistan', 'latitude' => 40.0, 'longitude' => 60.0],
|
||||
'TL' => ['name' => 'Timor-Leste', 'latitude' => -8.83, 'longitude' => 125.92],
|
||||
'TO' => ['name' => 'Tonga', 'latitude' => -20.0, 'longitude' => -175.0],
|
||||
'TT' => ['name' => 'Trinidad and Tobago', 'latitude' => 11.0, 'longitude' => -61.0],
|
||||
'TN' => ['name' => 'Tunisia', 'latitude' => 34.0, 'longitude' => 9.0],
|
||||
'TR' => ['name' => 'Turkey', 'latitude' => 39.0, 'longitude' => 35.0],
|
||||
'TV' => ['name' => 'Tuvalu', 'latitude' => -8.0, 'longitude' => 178.0],
|
||||
'TZ' => ['name' => 'Tanzania', 'latitude' => -6.0, 'longitude' => 35.0],
|
||||
'TW' => ['name' => 'Taiwan', 'latitude' => 23.5, 'longitude' => 121.0],
|
||||
'UG' => ['name' => 'Uganda', 'latitude' => 1.0, 'longitude' => 32.0],
|
||||
'UA' => ['name' => 'Ukraine', 'latitude' => 49.0, 'longitude' => 32.0],
|
||||
'UY' => ['name' => 'Uruguay', 'latitude' => -33.0, 'longitude' => -56.0],
|
||||
'US' => ['name' => 'United States', 'latitude' => 38.0, 'longitude' => -97.0],
|
||||
'UZ' => ['name' => 'Uzbekistan', 'latitude' => 41.0, 'longitude' => 64.0],
|
||||
'VA' => ['name' => 'Vatican City', 'latitude' => 41.9, 'longitude' => 12.45],
|
||||
'VC' => ['name' => 'Saint Vincent and the Grenadines', 'latitude' => 13.25, 'longitude' => -61.2],
|
||||
'VE' => ['name' => 'Venezuela', 'latitude' => 8.0, 'longitude' => -66.0],
|
||||
'VN' => ['name' => 'Vietnam', 'latitude' => 16.0, 'longitude' => 106.0],
|
||||
'VU' => ['name' => 'Vanuatu', 'latitude' => -16.0, 'longitude' => 167.0],
|
||||
'WS' => ['name' => 'Samoa', 'latitude' => -13.58, 'longitude' => -172.33],
|
||||
'YE' => ['name' => 'Yemen', 'latitude' => 15.0, 'longitude' => 48.0],
|
||||
'ZA' => ['name' => 'South Africa', 'latitude' => -29.0, 'longitude' => 24.0],
|
||||
'ZM' => ['name' => 'Zambia', 'latitude' => -15.0, 'longitude' => 30.0],
|
||||
'ZW' => ['name' => 'Zimbabwe', 'latitude' => -20.0, 'longitude' => 30.0],
|
||||
'AF',
|
||||
'AO',
|
||||
'AL',
|
||||
'AD',
|
||||
'AE',
|
||||
'AR',
|
||||
'AM',
|
||||
'AG',
|
||||
'AU',
|
||||
'AT',
|
||||
'AZ',
|
||||
'BI',
|
||||
'BE',
|
||||
'BJ',
|
||||
'BF',
|
||||
'BD',
|
||||
'BG',
|
||||
'BH',
|
||||
'BS',
|
||||
'BA',
|
||||
'BY',
|
||||
'BZ',
|
||||
'BO',
|
||||
'BR',
|
||||
'BB',
|
||||
'BN',
|
||||
'BT',
|
||||
'BW',
|
||||
'CF',
|
||||
'CA',
|
||||
'CH',
|
||||
'CL',
|
||||
'CN',
|
||||
'CI',
|
||||
'CM',
|
||||
'CD',
|
||||
'CG',
|
||||
'CO',
|
||||
'KM',
|
||||
'CV',
|
||||
'CR',
|
||||
'CU',
|
||||
'CY',
|
||||
'CZ',
|
||||
'DE',
|
||||
'DJ',
|
||||
'DM',
|
||||
'DK',
|
||||
'DO',
|
||||
'DZ',
|
||||
'EC',
|
||||
'EG',
|
||||
'ER',
|
||||
'ES',
|
||||
'EE',
|
||||
'ET',
|
||||
'FI',
|
||||
'FJ',
|
||||
'FR',
|
||||
'FM',
|
||||
'GA',
|
||||
'GB',
|
||||
'GE',
|
||||
'GH',
|
||||
'GN',
|
||||
'GM',
|
||||
'GW',
|
||||
'GQ',
|
||||
'GR',
|
||||
'GD',
|
||||
'GT',
|
||||
'GY',
|
||||
'HN',
|
||||
'HR',
|
||||
'HT',
|
||||
'HU',
|
||||
'ID',
|
||||
'IN',
|
||||
'IE',
|
||||
'IR',
|
||||
'IQ',
|
||||
'IS',
|
||||
'IL',
|
||||
'IT',
|
||||
'JM',
|
||||
'JO',
|
||||
'JP',
|
||||
'KZ',
|
||||
'KE',
|
||||
'KG',
|
||||
'KH',
|
||||
'KI',
|
||||
'KN',
|
||||
'KR',
|
||||
'KW',
|
||||
'LA',
|
||||
'LB',
|
||||
'LR',
|
||||
'LY',
|
||||
'LC',
|
||||
'LI',
|
||||
'LK',
|
||||
'LS',
|
||||
'LT',
|
||||
'LU',
|
||||
'LV',
|
||||
'MA',
|
||||
'MC',
|
||||
'MD',
|
||||
'MG',
|
||||
'MV',
|
||||
'MX',
|
||||
'MH',
|
||||
'MK',
|
||||
'ML',
|
||||
'MT',
|
||||
'MM',
|
||||
'ME',
|
||||
'MN',
|
||||
'MZ',
|
||||
'MR',
|
||||
'MU',
|
||||
'MW',
|
||||
'MY',
|
||||
'NA',
|
||||
'NE',
|
||||
'NG',
|
||||
'NI',
|
||||
'NL',
|
||||
'NO',
|
||||
'NP',
|
||||
'NR',
|
||||
'NZ',
|
||||
'OM',
|
||||
'PK',
|
||||
'PA',
|
||||
'PE',
|
||||
'PH',
|
||||
'PW',
|
||||
'PG',
|
||||
'PL',
|
||||
'KP',
|
||||
'PT',
|
||||
'PY',
|
||||
'QA',
|
||||
'RO',
|
||||
'RU',
|
||||
'RW',
|
||||
'SA',
|
||||
'SD',
|
||||
'SN',
|
||||
'SG',
|
||||
'SB',
|
||||
'SL',
|
||||
'SV',
|
||||
'SM',
|
||||
'SO',
|
||||
'RS',
|
||||
'SS',
|
||||
'ST',
|
||||
'SR',
|
||||
'SK',
|
||||
'SI',
|
||||
'SE',
|
||||
'SZ',
|
||||
'SC',
|
||||
'SY',
|
||||
'TD',
|
||||
'TG',
|
||||
'TH',
|
||||
'TJ',
|
||||
'TM',
|
||||
'TL',
|
||||
'TO',
|
||||
'TT',
|
||||
'TN',
|
||||
'TR',
|
||||
'TV',
|
||||
'TZ',
|
||||
'UG',
|
||||
'UA',
|
||||
'UY',
|
||||
'US',
|
||||
'UZ',
|
||||
'VA',
|
||||
'VC',
|
||||
'VE',
|
||||
'VN',
|
||||
'VU',
|
||||
'WS',
|
||||
'YE',
|
||||
'ZA',
|
||||
'ZM',
|
||||
'ZW',
|
||||
];
|
||||
|
||||
@@ -654,15 +654,10 @@ return [
|
||||
"nativeName" => "پښتو"
|
||||
],
|
||||
[
|
||||
"code" => "pt-pt",
|
||||
"code" => "pt",
|
||||
"name" => "Portuguese",
|
||||
"nativeName" => "Português"
|
||||
],
|
||||
[
|
||||
"code" => "pt-br",
|
||||
"name" => "Portuguese (Brazilian)",
|
||||
"nativeName" => "Português"
|
||||
],
|
||||
[
|
||||
"code" => "qu",
|
||||
"name" => "Quechua",
|
||||
@@ -924,13 +919,8 @@ return [
|
||||
"nativeName" => "Cuengh / Tôô / 壮语"
|
||||
],
|
||||
[
|
||||
"code" => "zh-cn",
|
||||
"name" => "Chinese (Simplified)",
|
||||
"nativeName" => "中文"
|
||||
],
|
||||
[
|
||||
"code" => "zh-tw",
|
||||
"name" => "Chinese (Traditional)",
|
||||
"code" => "zh",
|
||||
"name" => "Chinese",
|
||||
"nativeName" => "中文"
|
||||
],
|
||||
[
|
||||
|
||||
@@ -136,7 +136,6 @@ return [
|
||||
'NZ' => '64',
|
||||
'OM' => '968',
|
||||
'PK' => '92',
|
||||
'PS' => '970',
|
||||
'PA' => '507',
|
||||
'PE' => '51',
|
||||
'PH' => '63',
|
||||
@@ -180,7 +179,6 @@ return [
|
||||
'TN' => '216',
|
||||
'TR' => '90',
|
||||
'TV' => '688',
|
||||
'TW' => '886',
|
||||
'TZ' => '255',
|
||||
'UG' => '256',
|
||||
'UA' => '380',
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'email' => [
|
||||
'verification',
|
||||
'magicSession',
|
||||
'recovery',
|
||||
'invitation',
|
||||
'mfaChallenge',
|
||||
'sessionAlert',
|
||||
'otpSession'
|
||||
],
|
||||
'sms' => [
|
||||
'verification',
|
||||
'login',
|
||||
'invitation',
|
||||
'mfaChallenge'
|
||||
]
|
||||
];
|
||||
@@ -1,268 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="preconnect" href="https://assets.appwrite.io/" crossorigin>
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="supported-color-schemes" content="light dark">
|
||||
<style type="text/css">
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
supported-color-schemes: light dark;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark ) {
|
||||
body {
|
||||
color: #616b7c !important;
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
a {
|
||||
color: currentColor !important;
|
||||
}
|
||||
a.button {
|
||||
color: #ffffff !important;
|
||||
background-color: {{accentColor}} !important;
|
||||
border-color: {{accentColor}} !important;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
color: #373b4d !important;
|
||||
}
|
||||
h4 {
|
||||
color: #4f5769 !important;
|
||||
}
|
||||
p.security-phrase:not(:empty), hr {
|
||||
border-color: #e8e9f0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('https://assets.appwrite.io/fonts/inter/Inter-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
src: url('https://assets.appwrite.io/fonts/dm-sans/dm-sans-v16-latin-600.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@media (max-width:500px) {
|
||||
.mobile-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.main a {
|
||||
color: currentColor;
|
||||
}
|
||||
.main {
|
||||
padding: 32px;
|
||||
line-height: 1.5;
|
||||
color: #616b7c;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
font-family: "Inter", sans-serif;
|
||||
background-color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
a {
|
||||
color: currentColor;
|
||||
word-break: break-all;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-spacing: 0 !important;
|
||||
}
|
||||
table, tr, th, td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.main {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
margin-top: 32px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
color: #373b4d;
|
||||
}
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #373b4d;
|
||||
}
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #373b4d;
|
||||
line-height: 21px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h4 {
|
||||
font-family: "DM Sans", sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
color: #4f5769;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #e8e9f0;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
a.button {
|
||||
display: inline-block;
|
||||
background: {{accentColor}};
|
||||
color: #ffffff;
|
||||
border-radius: 8px;
|
||||
height: 48px;
|
||||
line-height: 24px;
|
||||
padding: 12px 20px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-color: {{accentColor}};
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
margin-right: 24px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
a.button:hover,
|
||||
a.button:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
.button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.social-icon {
|
||||
border-radius: 6px;
|
||||
background: rgba(216, 216, 219, 0.1);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.social-icon > img {
|
||||
margin: auto;
|
||||
}
|
||||
p.security-phrase:not(:empty) {
|
||||
opacity: 0.7;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 32px;
|
||||
padding-top: 32px;
|
||||
border-top: 1px solid #e8e9f0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
|
||||
{{preview}}
|
||||
<div>{{previewWhitespace}}</div>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<img
|
||||
height="26px"
|
||||
src="{{logoUrl}}"
|
||||
alt="{{platform}} logo"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="margin-top: 32px">
|
||||
<tr>
|
||||
<td>
|
||||
<h1>{{heading}}</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="margin-top: 16px">
|
||||
<tr>
|
||||
<td>
|
||||
{{body}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table
|
||||
style="
|
||||
padding-top: 32px;
|
||||
margin-top: 32px;
|
||||
border-top: solid 1px #e8e9f0;
|
||||
"
|
||||
>
|
||||
<tr>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="width: auto; margin: 0 auto">
|
||||
<tr>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="{{twitter}}"
|
||||
class="social-icon"
|
||||
title="Twitter"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/x.png" height="24" width="24" />
|
||||
</a>
|
||||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="{{discord}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/discord.png" height="24" width="24" />
|
||||
</a>
|
||||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="{{github}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/github.png" height="24" width="24" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="width: auto; margin: 0 auto; margin-top: 60px">
|
||||
<tr>
|
||||
<td><a href="{{terms}}">Terms</a></td>
|
||||
<td style="color: #e8e9f0">
|
||||
<div style="margin: 0 8px">|</div>
|
||||
</td>
|
||||
<td><a href="{{privacy}}">Privacy</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="text-align: center" align="center">
|
||||
© {{year}} {{platform}} | 251 Little Falls Drive, Wilmington 19808,
|
||||
Delaware, United States
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,158 +1,165 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="preconnect" href="https://assets.appwrite.io/" crossorigin>
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="supported-color-schemes" content="light dark">
|
||||
<style type="text/css">
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
supported-color-schemes: light dark;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark ) {
|
||||
body {
|
||||
color: #616b7c !important;
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
a {
|
||||
color: currentColor !important;
|
||||
}
|
||||
a.button {
|
||||
color: #ffffff !important;
|
||||
background-color: #2D2D31 !important;
|
||||
border-color: #414146 !important;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
color: #373b4d !important;
|
||||
}
|
||||
h4 {
|
||||
color: #4f5769 !important;
|
||||
}
|
||||
p.security-phrase:not(:empty), hr {
|
||||
border-color: #e8e9f0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('https://assets.appwrite.io/fonts/inter/Inter-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DM Sans';
|
||||
src: url('https://assets.appwrite.io/fonts/dm-sans/dm-sans-v16-latin-600.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.main {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
margin-top: 32px;
|
||||
padding: 32px;
|
||||
line-height: 1.5;
|
||||
color: #616b7c;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
font-family: "Inter", sans-serif;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.main a {
|
||||
color: currentColor;
|
||||
word-break: break-all;
|
||||
}
|
||||
.main a.button {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
padding: 9px 14px;
|
||||
color: #ffffff;
|
||||
background-color: #2D2D31;
|
||||
border: 1px solid #414146;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.main a.button:hover,
|
||||
.main a.button:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-spacing: 0 !important;
|
||||
}
|
||||
table, tr, th, td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
color: #373b4d;
|
||||
}
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #373b4d;
|
||||
}
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #373b4d;
|
||||
line-height: 21px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h4 {
|
||||
font-family: "DM Sans", sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
color: #4f5769;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #e8e9f0;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
p.security-phrase:not(:empty) {
|
||||
opacity: 0.7;
|
||||
margin-top: 32px;
|
||||
padding-top: 32px;
|
||||
border-top: 1px solid #e8e9f0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>{{subject}}</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: {{bg-body}};
|
||||
color: {{text-content}};
|
||||
font-family: sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table td {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.body {
|
||||
background-color: {{bg-body}};
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: block;
|
||||
margin: 0 auto !important;
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
color: {{text-content}};
|
||||
}
|
||||
|
||||
.main {
|
||||
background: {{bg-content}};
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
box-sizing: border-box;
|
||||
padding: 30px 30px 15px 30px;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
a {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 620px) {
|
||||
.container {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.apple-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
#MessageViewBody a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="direction: {{direction}}">
|
||||
|
||||
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
|
||||
{{preview}}
|
||||
<div>{{previewWhitespace}}</div>
|
||||
</div>
|
||||
|
||||
<div class="main" style="max-width:650px; word-wrap: break-word; overflow-wrap: break-word; word-break: normal; margin:0 auto;">
|
||||
<table style="margin-top: 32px">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="container">
|
||||
<div class="content">
|
||||
<table role="presentation" class="main">
|
||||
<tr>
|
||||
<td>
|
||||
{{body}}
|
||||
</td>
|
||||
<td class="wrapper">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p>{{hello}}</p>
|
||||
<p>{{body}}</p>
|
||||
<a href="{{redirect}}" target="_blank">{{redirect}}</a>
|
||||
<p></br>{{footer}}</p>
|
||||
<p>{{thanks}}
|
||||
</br>
|
||||
{{signature}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- <div style="text-align: center; line-height: 25px; margin: 15px 0; font-size: 12px; color: #40404c;">
|
||||
<a href="https://appwrite.io" style="text-decoration: none; color: #40404c;">Powered by <img src="https://appwrite.io/images/appwrite-footer-light.svg" height="15" style="margin: -3px 0" /></a>
|
||||
</div> -->
|
||||
</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,22 +0,0 @@
|
||||
<p>Hello,</p>
|
||||
<p>Your domain <strong>{{domain}}</strong> failed to generate certificate after <strong>{{attempts}}</strong> consecutive attempts with the following error:</p>
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 8px; background-color: #ffffff;">
|
||||
<p style="text-align: start; font-size: 14px; font-family: Inter; color: #414146; text-decoration: none; border-radius: 8px; padding: 32px; border: 1px solid #EDEDF0; display: inline-block; word-break: break-word;">
|
||||
{{error}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>We suggest to follow the below steps:</p>
|
||||
<ol>
|
||||
<li>Examine the logs above to try and identify the issue</li>
|
||||
<li>Ensure your domain has not expired</li>
|
||||
<li>Check your DNS configuration for any unexpected values</li>
|
||||
<li>Manually re-trigger a certificate generation from the Appwrite Console</li>
|
||||
</ol>
|
||||
|
||||
<p>The existing certificate will remain valid for 30 days from the initial failure. It is highly recommended to investigate this issue; failing to do so will lead to security vulnerabilities.</p>
|
||||
@@ -1,8 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
<p>{{body}}</p>
|
||||
<p>{{footer}}</p>
|
||||
<p style="margin-bottom: 32px">
|
||||
{{thanks}}
|
||||
<br/>
|
||||
{{signature}}
|
||||
</p>
|
||||
@@ -1,9 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
<p>{{body}}</p>
|
||||
<p><a href="{{redirect}}" target="_blank" class="button">{{buttonText}}</a></p>
|
||||
<p>{{footer}}</p>
|
||||
<p style="margin-bottom: 32px">
|
||||
{{thanks}}
|
||||
<br/>
|
||||
{{signature}}
|
||||
</p>
|
||||
@@ -1,24 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
|
||||
<p>{{optionButton}}</p>
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 8px; background-color: #19191D;">
|
||||
<a rel="noopener" target="_blank" href="{{redirect}}" class="button">{{buttonText}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>{{optionUrl}}</p>
|
||||
|
||||
<a href="{{redirect}}" target="_blank" style="font-size: 12px; line-height: 100%;">{{redirect}}</a>
|
||||
|
||||
<p>{{clientInfo}}</p>
|
||||
|
||||
<p style="margin-bottom: 0px;">{{thanks}}</p>
|
||||
<p style="margin-top: 0px;">{{signature}}</p>
|
||||
|
||||
<hr style="margin-block-start: 1rem; margin-block-end: 1rem;">
|
||||
|
||||
<p style="opacity: 0.7;">{{securityPhrase}}</p>
|
||||
@@ -1,16 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
|
||||
<p>{{description}}</p>
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 8px; background-color: #ffffff;">
|
||||
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: 'Inter', sans-serif; color: #414146; text-decoration: none; border-radius: 8px; margin-top: 0px; margin-bottom: 0px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold;">{{otp}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>{{clientInfo}}</p>
|
||||
|
||||
<p style="margin-bottom: 0px;">{{thanks}}</p>
|
||||
<p style="margin-top: 0px;">{{signature}}</p>
|
||||
@@ -1,18 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
|
||||
<p>{{description}}</p>
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; display: inline-block;">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 8px; background-color: #ffffff;">
|
||||
<p style="font-size: 24px; text-indent: 18px; letter-spacing: 18px; font-family: 'Inter', sans-serif; color: #414146; text-decoration: none; border-radius: 8px; margin-top: 0px; margin-bottom: 0px; padding: 24px 12px; border: 1px solid #EDEDF0; display: inline-block; font-weight: bold; ">{{otp}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>{{clientInfo}}</p>
|
||||
|
||||
<p style="margin-bottom: 0px;">{{thanks}}</p>
|
||||
<p style="margin-top: 0px;">{{signature}}</p>
|
||||
|
||||
<p class="security-phrase">{{securityPhrase}}</p>
|
||||
@@ -1,14 +0,0 @@
|
||||
<p>{{hello}}</p>
|
||||
|
||||
<p>{{body}}</p>
|
||||
|
||||
<ol>
|
||||
<li>{{listDevice}}</li>
|
||||
<li>{{listIpAddress}}</li>
|
||||
<li>{{listCountry}}</li>
|
||||
</ol>
|
||||
|
||||
<p>{{footer}}</p>
|
||||
|
||||
<p style="margin-bottom: 0px;">{{thanks}}</p>
|
||||
<p style="margin-top: 0px;">{{signature}}</p>
|
||||
@@ -1,12 +0,0 @@
|
||||
<p style="margin-block-start: 0;">Hello,</p>
|
||||
|
||||
<p>This email ensures your custom SMTP configuration is working correctly. Please review your sender Information details:</p>
|
||||
|
||||
<p style="margin-block-end: 0;">From: <strong>{{from}}</strong></p>
|
||||
<p style="margin-block-start: 0;">Reply-To: <strong>{{replyTo}}</strong></p>
|
||||
|
||||
<p>If this email was labeled as spam, please check your SMTP server settings to ensure they meet your provider's requirements. Often, missing DNS configurations or security checks mandated by your SMTP provider affect email delivery.</p>
|
||||
<p>If you have trouble with the sender's image, ensure it is set in the <a href="https://gravatar.com/">Gravatar database</a>.</p>
|
||||
|
||||
<p style="margin-block-end: 0;">Best regards,</p>
|
||||
<p style="margin-block-start: 0;">Appwrite team</p>
|
||||
@@ -1,20 +0,0 @@
|
||||
<p>Hi <strong>{{user}}</strong>,</p>
|
||||
<p>Your webhook <strong>{{webhook}}</strong> on project <strong>{{project}}</strong> has been paused after {{attempts}} consecutive failures.</p>
|
||||
<p>Webhook Endpoint: <strong>{{url}}</strong></p>
|
||||
<p>Error: <strong>{{error}}</strong></p>
|
||||
<p>To restore your webhook's functionality and reset attempts, we suggest to follow the below steps:</p>
|
||||
<ol>
|
||||
<li>Examine the logs of both Appwrite Console and your webhook server to identify the issue.</li>
|
||||
<li>Investigate potential network issues and use webhook testing tools to verify expected behaviour.</li>
|
||||
<li>Ensure the webhook endpoint is reachable and configured to accept incoming POST requests.</li>
|
||||
<li>Confirm that the webhook doesn't return error status codes such as 400 or 500.</li>
|
||||
</ol>
|
||||
<p>After the issue is resolved, please make sure to re-enable the webhook directly through the webhook settings.</p>
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="padding-top: 10px; padding-bottom: 10px; margin-top: 32px">
|
||||
<tr>
|
||||
<td style="border-radius: 8px; display: block; width: 100%;">
|
||||
<a class="mobile-full-width" rel="noopener" target="_blank" href="{{host}}{{path}}" style="font-size: 14px; font-family: Inter; color: #ffffff; text-decoration: none; background-color: #2D2D31; border-radius: 8px; padding: 9px 14px; border: 1px solid #414146; display: inline-block; text-align:center; box-sizing: border-box;">Webhook settings</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -1 +0,0 @@
|
||||
{{token}}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"Wie nie waag nie, sal nie wen nie.\"",
|
||||
"settings.locale": "af",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} span",
|
||||
"emails.sender": "%s span",
|
||||
"emails.verification.subject": "Rekening Bevestiging",
|
||||
"emails.verification.hello": "Goeie dag {{user}},",
|
||||
"emails.verification.hello": "Goeie dag {{name}}",
|
||||
"emails.verification.body": "Volg hierdie skakel om u e-pos adres te bevestig.",
|
||||
"emails.verification.footer": "Ignoreer gerus hierdie boodskap as u nie die versoek gestuur het om u adres te bevestig nie.",
|
||||
"emails.verification.thanks": "Baie dankie,",
|
||||
"emails.verification.buttonText": "Bevestig e-posadres",
|
||||
"emails.verification.thanks": "Baie dankie",
|
||||
"emails.verification.signature": "Die {{project}} span",
|
||||
"emails.magicSession.subject": "Teken aan",
|
||||
"emails.magicSession.hello": "Goeie dag,",
|
||||
"emails.magicSession.thanks": "Baie dankie,",
|
||||
"emails.magicSession.body": "Volg hierdie skakel om in te teken.",
|
||||
"emails.magicSession.footer": "Ignoreer gerus hierdie boodskap as u nie die versoek gestuur het om met die' adres in te teken nie.",
|
||||
"emails.magicSession.thanks": "Baie dankie",
|
||||
"emails.magicSession.signature": "Die {{project}} span",
|
||||
"emails.recovery.subject": "Herstel Wagwoord",
|
||||
"emails.recovery.hello": "Goeie dag {{user}},",
|
||||
"emails.recovery.hello": "Goeie dag {{name}}",
|
||||
"emails.recovery.body": "Volg hierdie skakel om u {{project}} wagwoord te herstel.",
|
||||
"emails.recovery.footer": "Ignoreer gerus hierdie boodskap as u nie die versoek gestuur het om u wagwoord te herstel nie.",
|
||||
"emails.recovery.thanks": "Baie dankie,",
|
||||
"emails.recovery.buttonText": "Stel wagwoord terug",
|
||||
"emails.recovery.thanks": "Baie dankie",
|
||||
"emails.recovery.signature": "Die {{project}} span",
|
||||
"emails.invitation.subject": "Uitnodiging om by die {{team}} span aan te sluit by {{project}}",
|
||||
"emails.invitation.subject": "Uitnodiging om by die %s span aan te sluit by %s",
|
||||
"emails.invitation.hello": "Goeie dag,",
|
||||
"emails.invitation.body": "Hierdie boodskap is aan u gestuur omdat {{owner}} u uitnooi om 'n lid van die {{team}} groep by die {{project}} projek te wees.",
|
||||
"emails.invitation.footer": "As u nie belang stel nie, kan u gerus hierdie boodskap ignoreer.",
|
||||
"emails.invitation.thanks": "Baie dankie,",
|
||||
"emails.invitation.buttonText": "Aanvaar uitnodiging na {{team}}",
|
||||
"emails.invitation.thanks": "Baie dankie",
|
||||
"emails.invitation.signature": "Die {{project}} span",
|
||||
"locale.country.unknown": "Onbekend",
|
||||
"countries.af": "Afghanistan",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Kroasië",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Nieu-Seeland",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palestine",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Filippyne",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Tunisië",
|
||||
"countries.tr": "Turkye",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwan",
|
||||
"countries.tz": "Tanzanië",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Oekraïne",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "Noord-Amerika",
|
||||
"continents.oc": "Oseanië",
|
||||
"continents.sa": "Suid-Amerika",
|
||||
"emails.magicSession.optionButton": "Klik op die knoppie hieronder om veilig aan te meld by jou {{project}} rekening. Dit sal oor 1 uur verval.",
|
||||
"emails.magicSession.buttonText": "Meld aan by {{project}}",
|
||||
"emails.magicSession.clientInfo": "Hierdie teken-in is aangevra met behulp van {{agentClient}} op {{agentDevice}} {{agentOs}}. As jy nie die teken-in versoek het nie, kan jy hierdie e-pos veilig ignoreer.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Die sekuriteitsfrase vir hierdie e-pos is {{phrase}}. Jy kan hierdie e-pos vertrou as hierdie frase ooreenstem met die frase wat tydens aanmelding getoon is.",
|
||||
"emails.magicSession.optionUrl": "As u nie met die knoppie hierbo kan aanmeld nie, besoek asseblief die volgende skakel:",
|
||||
"emails.otpSession.subject": "{{project}} Aanteken",
|
||||
"emails.otpSession.hello": "Hallo,",
|
||||
"emails.otpSession.description": "Voer die volgende verifikasiekode in wanneer daar versoek word om veilig aan te meld by jou {{project}} rekening. Dit sal verval oor 15 minute.",
|
||||
"emails.otpSession.clientInfo": "Hierdie aanmelding is versoek met behulp van {{agentClient}} op {{agentDevice}} {{agentOs}}. As jy nie die aanmelding versoek het nie, kan jy hierdie e-pos veilig ignoreer.",
|
||||
"emails.otpSession.securityPhrase": "Die veiligheidsfrase vir hierdie e-pos is {{phrase}}. Jy kan hierdie e-pos vertrou as hierdie frase ooreenstem met die frase wat gewys is tydens aanmelding.",
|
||||
"emails.otpSession.thanks": "Dankie,",
|
||||
"emails.otpSession.signature": "{{project}} span"
|
||||
}
|
||||
"continents.sa": "Suid-Amerika"
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
{
|
||||
"settings.inspire": "\"الفن ديال الحكمة هو الفن ديال أنك تعرف أش تنخّل.\"",
|
||||
"settings.locale": "ar-ma",
|
||||
"settings.direction": "rtl",
|
||||
"emails.sender": "فرقة {{project}}",
|
||||
"emails.verification.subject": "التيْقان ديال الحساب",
|
||||
"emails.verification.hello": "السلام {{user}}،",
|
||||
"emails.verification.body": "تبّع هاد الوصلة باش تيقّن لادريسة تاع ليميل ديالك.",
|
||||
"emails.verification.footer": "إلا ماشي نتا اللي طلبتي تيقّن هاد لادريسة تاع ليميل، ممكن تنخّل هاد البرية.",
|
||||
"emails.verification.thanks": "شكرا،",
|
||||
"emails.verification.buttonText": "تأكيد عنوان البريد الإلكتروني",
|
||||
"emails.verification.signature": "فرقة {{project}}",
|
||||
"emails.magicSession.subject": "تكونيكطا",
|
||||
"emails.magicSession.hello": "السلام،",
|
||||
"emails.magicSession.thanks": "شكرا،",
|
||||
"emails.magicSession.signature": "فرقة {{project}}",
|
||||
"emails.recovery.subject": "تبدال كلمة السر",
|
||||
"emails.recovery.hello": "السلام {{user}}،",
|
||||
"emails.recovery.body": "تبّع هاد الوصلة باش تبدّل كلمة السر تاع {{project}}.",
|
||||
"emails.recovery.footer": "إلا ماشي نتا اللي طلبتي تبدّل كلمة السر، ممكن تنخّل هاد البرية.",
|
||||
"emails.recovery.thanks": "شكرا،",
|
||||
"emails.recovery.buttonText": "إعادة تعيين كلمة السر",
|
||||
"emails.recovery.signature": "فرقة {{project}}",
|
||||
"emails.invitation.subject": "عراضة ل فرقة {{team}} ف {{project}}",
|
||||
"emails.invitation.hello": "السلام،",
|
||||
"emails.invitation.body": "هاد البرية تصيفطات ليك حيت {{owner}} بغى يعرض عليك تولّي عضو ف فرقة {{team}} عند {{project}}.",
|
||||
"emails.invitation.footer": "إلا كنتي ما مسوّقش, ممكن تنخّل هاد البرية.",
|
||||
"emails.invitation.thanks": "شكرا،",
|
||||
"emails.invitation.buttonText": "اقبل الدعوة إلى {{team}}",
|
||||
"emails.invitation.signature": "فرقة {{project}}",
|
||||
"emails.certificate.subject": "السرتافيكة فشلات ل {{domain}}",
|
||||
"emails.certificate.hello": "السلام،",
|
||||
"emails.certificate.body": "السرتافيكة ديال الضومين ديالك '{{domain}}' ما قدّاتش تجينيرا. هادي هي المحاولة نمرة {{attempt}}, السبب ديال هاد الفشل هو: {{error}}",
|
||||
"emails.certificate.footer": "السرتافيكة الفايتة ديالك غاتبقى مزيانة لمدة 30 يوم من عند أول فشل. كانشجعوك بزاف أنك تبقشش فهاد الموضوع, وا إلّا الضومين ديالك ما غايبقاش خدّام فيه الـ SSL.",
|
||||
"emails.certificate.thanks": "شكرا،",
|
||||
"emails.certificate.signature": "فرقة {{project}}",
|
||||
"locale.country.unknown": "ما معروفش",
|
||||
"countries.af": "أفغانستان",
|
||||
"countries.ao": "أنڭولا",
|
||||
"countries.al": "ألبانيا",
|
||||
"countries.ad": "أندورا",
|
||||
"countries.ae": "الإمارات العربية المتّاحدة",
|
||||
"countries.ar": "الأرجنتين",
|
||||
"countries.am": "أرمينيا",
|
||||
"countries.ag": "أنتيڭوا وبربودا",
|
||||
"countries.au": "ؤسطراليا",
|
||||
"countries.at": "النامسا",
|
||||
"countries.az": "أديربيجان",
|
||||
"countries.bi": "بوروندي",
|
||||
"countries.be": "بلجيكا",
|
||||
"countries.bj": "بينين",
|
||||
"countries.bf": "بوركينا فاصو",
|
||||
"countries.bd": "بنڭلاديش",
|
||||
"countries.bg": "بلڭاريا",
|
||||
"countries.bh": "البحرين",
|
||||
"countries.bs": "دزيرات البهاما",
|
||||
"countries.ba": "البوسنة ؤ الهرسك",
|
||||
"countries.by": "بيلاروسيا",
|
||||
"countries.bz": "بيليز",
|
||||
"countries.bo": "بوليڤيا",
|
||||
"countries.br": "البرازيل",
|
||||
"countries.bb": "باربادوس",
|
||||
"countries.bn": "بروناي",
|
||||
"countries.bt": "بوتان",
|
||||
"countries.bw": "بوتسوانا",
|
||||
"countries.cf": "جمهورية إفريقيا الوسطانية",
|
||||
"countries.ca": "كانادا",
|
||||
"countries.ch": "سويسرا",
|
||||
"countries.cl": "تشيلي",
|
||||
"countries.cn": "الشينوا",
|
||||
"countries.ci": "ساحل العاج",
|
||||
"countries.cm": "الكاميرون",
|
||||
"countries.cd": "جمهورية الكونڭو الديمقراطية",
|
||||
"countries.cg": "جمهورية الكونڭو",
|
||||
"countries.co": "كولومبيا",
|
||||
"countries.km": "دزيرات القومور",
|
||||
"countries.cv": "الراس الخضر",
|
||||
"countries.cr": "كوسطاريكا",
|
||||
"countries.cu": "كوبا",
|
||||
"countries.cy": "قوبروص",
|
||||
"countries.cz": "التشيك",
|
||||
"countries.de": "ألمانيا",
|
||||
"countries.dj": "دجيبوتي",
|
||||
"countries.dm": "ضومينيكا",
|
||||
"countries.dk": "الدنمارك",
|
||||
"countries.do": "جمهورية الضومينيكان",
|
||||
"countries.dz": "الدزاير",
|
||||
"countries.ec": "إكوادور",
|
||||
"countries.eg": "مصر",
|
||||
"countries.er": "إريتريا",
|
||||
"countries.es": "سبانيا",
|
||||
"countries.ee": "إسطونيا",
|
||||
"countries.et": "إتيوپيا",
|
||||
"countries.fi": "فينلاندا",
|
||||
"countries.fj": "فيدجي",
|
||||
"countries.fr": "فرانسا",
|
||||
"countries.fm": "ميكرونيزيا",
|
||||
"countries.ga": "الڭابون",
|
||||
"countries.gb": "المملكة المتّاحدة",
|
||||
"countries.ge": "تجورجيا",
|
||||
"countries.gh": "غانا",
|
||||
"countries.gn": "غينيا",
|
||||
"countries.gm": "ڭامبيا",
|
||||
"countries.gw": "غينيا بيساو",
|
||||
"countries.gq": "غينيا الستوائية",
|
||||
"countries.gr": "اليونان",
|
||||
"countries.gd": "ڭرينادا",
|
||||
"countries.gt": "ڭواتيمالا",
|
||||
"countries.gy": "ڭيانا",
|
||||
"countries.hn": "هوندوراس",
|
||||
"countries.hr": "كرواتيا",
|
||||
"countries.ht": "هايتي",
|
||||
"countries.hu": "الماجر",
|
||||
"countries.id": "إندونيسيا",
|
||||
"countries.in": "الهند",
|
||||
"countries.ie": "إرلاندا",
|
||||
"countries.ir": "إران",
|
||||
"countries.iq": "العراق",
|
||||
"countries.is": "إسلاندا",
|
||||
"countries.il": "إسرائيل",
|
||||
"countries.it": "الطاليان",
|
||||
"countries.jm": "جامايكا",
|
||||
"countries.jo": "الأردن",
|
||||
"countries.jp": "الجاپون",
|
||||
"countries.kz": "كازاخستان",
|
||||
"countries.ke": "كينيا",
|
||||
"countries.kg": "قيرغيزستان",
|
||||
"countries.kh": "كمبوديا",
|
||||
"countries.ki": "كيريباتي",
|
||||
"countries.kn": "سانت كيتس ؤ نيفيس",
|
||||
"countries.kr": "كوريا الجنوبية",
|
||||
"countries.kw": "الكويت",
|
||||
"countries.la": "لاوس",
|
||||
"countries.lb": "لبنان",
|
||||
"countries.lr": "ليبيريا",
|
||||
"countries.ly": "ليبيا",
|
||||
"countries.lc": "سانت لوسيا",
|
||||
"countries.li": "ليختنشتاين",
|
||||
"countries.lk": "سري لانكا",
|
||||
"countries.ls": "ليسوتو",
|
||||
"countries.lt": "ليتوانيا",
|
||||
"countries.lu": "لوكسمبورڭ",
|
||||
"countries.lv": "لاتفيا",
|
||||
"countries.ma": "المغريب",
|
||||
"countries.mc": "موناكو",
|
||||
"countries.md": "مولضوڤا",
|
||||
"countries.mg": "ماداغشقار",
|
||||
"countries.mv": "دزيرات المالديڤ",
|
||||
"countries.mx": "الميكسيك",
|
||||
"countries.mh": "دزيرات مارشال",
|
||||
"countries.mk": "مقدونيا",
|
||||
"countries.ml": "مالي",
|
||||
"countries.mt": "مالطا",
|
||||
"countries.mm": "ميانمار",
|
||||
"countries.me": "مونطينيڭرو",
|
||||
"countries.mn": "منغوليا",
|
||||
"countries.mz": "الموزمبيق",
|
||||
"countries.mr": "موريتانيا",
|
||||
"countries.mu": "موريشيوس",
|
||||
"countries.mw": "مالاوي",
|
||||
"countries.my": "ماليزيا",
|
||||
"countries.na": "ناميبيا",
|
||||
"countries.ne": "النيجر",
|
||||
"countries.ng": "نيجيريا",
|
||||
"countries.ni": "نيكاراڭوا",
|
||||
"countries.nl": "هولاندا",
|
||||
"countries.no": "النرويج",
|
||||
"countries.np": "نيپال",
|
||||
"countries.nr": "ناورو",
|
||||
"countries.nz": "نيوزيلاندا",
|
||||
"countries.om": "عمّان",
|
||||
"countries.pk": "پاكيستان",
|
||||
"countries.pa": "پاناما",
|
||||
"countries.pe": "الپيرو",
|
||||
"countries.ph": "الفيليپين",
|
||||
"countries.pw": "پالاو",
|
||||
"countries.pg": "پاپوا غينيا الجديدة",
|
||||
"countries.pl": "پولاندا",
|
||||
"countries.kp": "كوريا الشمالية",
|
||||
"countries.pt": "البرطقيز",
|
||||
"countries.py": "الپاراڭواي",
|
||||
"countries.qa": "قطر",
|
||||
"countries.ro": "رومانيا",
|
||||
"countries.ru": "روسيا",
|
||||
"countries.rw": "روّاندا",
|
||||
"countries.sa": "المملكة العربية السعودية",
|
||||
"countries.sd": "السودان",
|
||||
"countries.sn": "السينيڭال",
|
||||
"countries.sg": "سنغافورة",
|
||||
"countries.sb": "دزيرات سليمان",
|
||||
"countries.sl": "صييراليون",
|
||||
"countries.sv": "السالڤاضور",
|
||||
"countries.sm": "سان مارينو",
|
||||
"countries.so": "الصومال",
|
||||
"countries.rs": "صيربيا",
|
||||
"countries.ss": "جنوب السودان",
|
||||
"countries.st": "صاو طومي ؤ پرينسيپي",
|
||||
"countries.sr": "سورينام",
|
||||
"countries.sk": "صلوڤاكيا",
|
||||
"countries.si": "صلوڤينيا",
|
||||
"countries.se": "السويد",
|
||||
"countries.sz": "سوازيلاند",
|
||||
"countries.sc": "السيشيل",
|
||||
"countries.sy": "سوريا",
|
||||
"countries.td": "تشاد",
|
||||
"countries.tg": "الطوڭو",
|
||||
"countries.th": "الطايلوند",
|
||||
"countries.tj": "طادجيكيستان",
|
||||
"countries.tm": "تركمانيستان",
|
||||
"countries.tl": "تيمور الشرقية",
|
||||
"countries.to": "تونڭا",
|
||||
"countries.tt": "ترينيداد ؤ طوباڭو",
|
||||
"countries.tn": "تونس",
|
||||
"countries.tr": "توركيا",
|
||||
"countries.tv": "توڤالو",
|
||||
"countries.tz": "طنزانيا",
|
||||
"countries.ug": "ؤڭاندا",
|
||||
"countries.ua": "ؤكرانيا",
|
||||
"countries.uy": "ؤروڭواي",
|
||||
"countries.us": "ميريكان",
|
||||
"countries.uz": "ؤزباكيستان",
|
||||
"countries.va": "مدينة الڤاتيكان",
|
||||
"countries.vc": "سانت ڤانسون ؤ دزيرات ڭرينادين",
|
||||
"countries.ve": "ڤينيزويلا",
|
||||
"countries.vn": "ڤيطنام",
|
||||
"countries.vu": "ڤانواتو",
|
||||
"countries.ws": "ساموا",
|
||||
"countries.ye": "اليمن",
|
||||
"countries.za": "جنوب إفريقيا",
|
||||
"countries.zm": "زامبيا",
|
||||
"countries.zw": "زيمبابوي",
|
||||
"continents.af": "أفريقيا",
|
||||
"continents.an": "القارة القطبية الجنوبية",
|
||||
"continents.as": "أسيا",
|
||||
"continents.eu": "ؤروپا",
|
||||
"continents.na": "ميريكان الشمالية",
|
||||
"continents.oc": "ؤقيانوسيا",
|
||||
"continents.sa": "ميريكان الجنوبية"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"فن الحكمة هو فن معرفة ما يجب التغاضي عنه.\"",
|
||||
"settings.locale": "ar",
|
||||
"settings.direction": "rtl",
|
||||
"emails.sender": "فريق {{project}}",
|
||||
"emails.sender": "فريق %s",
|
||||
"emails.verification.subject": "تأكيد الحساب",
|
||||
"emails.verification.hello": "مرحبا {{user}}،",
|
||||
"emails.verification.hello": "مرحبا {{name}}",
|
||||
"emails.verification.body": "برجاء اتباع الرابط التالي لتأكيد بريدك الإلكتروني",
|
||||
"emails.verification.footer": "لو لم تطلب تأكيد هذا البريد الإلكتروني، يمكنك تجاهل هذه الرسالة",
|
||||
"emails.verification.thanks": "شكرا،",
|
||||
"emails.verification.buttonText": "تأكيد عنوان البريد الإلكتروني",
|
||||
"emails.verification.thanks": "شكرا",
|
||||
"emails.verification.signature": "فريق {{project}}",
|
||||
"emails.magicSession.subject": "تسجيل الدخول",
|
||||
"emails.magicSession.hello": "أهلا،",
|
||||
"emails.magicSession.thanks": "شكرا،",
|
||||
"emails.magicSession.body": "اتبع هذا الرابط لتسجيل الدخول",
|
||||
"emails.magicSession.footer": "لو لم تطلب تسجيل الدخول بهذا البريد الاكتروني ، يمكنك تجاهل هذه الرسالة",
|
||||
"emails.magicSession.thanks": "شكرا",
|
||||
"emails.magicSession.signature": "فريق {{project}}",
|
||||
"emails.recovery.subject": "تغيير كلمة السر",
|
||||
"emails.recovery.hello": "أهلا {{user}}،",
|
||||
"emails.recovery.hello": "أهلا {{name}}",
|
||||
"emails.recovery.body": "برجاء اتباع الراط التالي لتغيير كلمة السر الخاصة بـ{{project}}",
|
||||
"emails.recovery.footer": "لولم تطلب تغيير كلمة السر، يمكنك تجاهل هذه الرسالة",
|
||||
"emails.recovery.thanks": "شكرا،",
|
||||
"emails.recovery.buttonText": "إعادة تعيين كلمة المرور",
|
||||
"emails.recovery.thanks": "شكرا",
|
||||
"emails.recovery.signature": "فريق {{project}}",
|
||||
"emails.invitation.subject": "دعوة لفريق {{team}} في {{project}}",
|
||||
"emails.invitation.hello": "أهلا،",
|
||||
"emails.invitation.subject": "دعوة لفريق %s في %s",
|
||||
"emails.invitation.hello": "أهلا",
|
||||
"emails.invitation.body": "هذة الرسالة تم ارسالها لك لأن {{owner}} ارسل لك دعوة لتكون عضوا بفريق {{team}} في {{project}}",
|
||||
"emails.invitation.footer": "اذا كنت غير مهتم، يمكنك تجاهل هذه الرسالة",
|
||||
"emails.invitation.thanks": "شكرا،",
|
||||
"emails.invitation.buttonText": "قبول الدعوة إلى {{team}}",
|
||||
"emails.invitation.thanks": "شكرا",
|
||||
"emails.invitation.signature": "فريق {{project}}",
|
||||
"locale.country.unknown": "مجهول",
|
||||
"countries.af": "أفغانستان",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "غرينادا",
|
||||
"countries.gt": "غواتيمالا",
|
||||
"countries.gy": "غيانا",
|
||||
"countries.hk": "هونغ كونغ",
|
||||
"countries.hn": "هندوراس",
|
||||
"countries.hr": "كرواتيا",
|
||||
"countries.ht": "هايتي",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "نيوزيلندا",
|
||||
"countries.om": "عمان",
|
||||
"countries.pk": "باكستان",
|
||||
"countries.ps": "فلسطين",
|
||||
"countries.pa": "بنما",
|
||||
"countries.pe": "بيرو",
|
||||
"countries.ph": "الفلبين",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "تونس",
|
||||
"countries.tr": "تركيا",
|
||||
"countries.tv": "توفالو",
|
||||
"countries.tw": "تايوان",
|
||||
"countries.tz": "تنزانيا",
|
||||
"countries.ug": "أوغندا",
|
||||
"countries.ua": "أوكرانيا",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "أوروبا",
|
||||
"continents.na": "امريكا الشمالية",
|
||||
"continents.oc": "أوقيانوسيا",
|
||||
"continents.sa": "امريكا الجنوبية",
|
||||
"emails.magicSession.optionButton": "انقر على الزر أدناه لتسجيل الدخول بأمان إلى حساب {{project}} الخاص بك. سينتهي في غضون ساعة واحدة.",
|
||||
"emails.magicSession.buttonText": "تسجيل الدخول إلى {{project}}",
|
||||
"emails.magicSession.clientInfo": "تم طلب هذا الدخول باستخدام {{agentClient}} على {{agentDevice}} {{agentOs}}. إذا لم تطلب الدخول، يمكنك تجاهل هذا البريد الإلكتروني بأمان.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "عبارة الأمان لهذا البريد الإلكتروني هي {{phrase}}. يمكنك الوثوق بهذا البريد الإلكتروني إذا كانت هذه العبارة تطابق العبارة التي تظهر أثناء التسجيل.",
|
||||
"emails.magicSession.optionUrl": "إذا لم تتمكن من تسجيل الدخول باستخدام الزر أعلاه، يرجى زيارة الرابط التالي:",
|
||||
"emails.otpSession.subject": "تسجيل دخول {{project}}",
|
||||
"emails.otpSession.hello": "مرحبا،",
|
||||
"emails.otpSession.description": "أدخل رمز التحقق التالي عندما يُطلب منك لتسجيل الدخول بأمان إلى حساب {{project}} الخاص بك. سينتهي صلاحيته في غضون 15 دقيقة.",
|
||||
"emails.otpSession.clientInfo": "تم طلب هذا الدخول باستخدام {{agentClient}} على جهاز {{agentDevice}} {{agentOs}}. إذا لم تطلب الدخول، يمكنك تجاهل هذا البريد الإلكتروني بأمان.",
|
||||
"emails.otpSession.securityPhrase": "عبارة الأمان لهذا البريد الإلكتروني هي {{phrase}}. يمكنك الوثوق بهذا البريد الإلكتروني إذا كانت هذه العبارة تتطابق مع العبارة المعروضة أثناء تسجيل الدخول.",
|
||||
"emails.otpSession.thanks": "شكرًا،",
|
||||
"emails.otpSession.signature": "فريق {{project}}"
|
||||
}
|
||||
"continents.sa": "امريكا الجنوبية"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"জ্ঞানী হোৱাৰ কলা হৈছে কি উপেক্ষা কৰিব লাগে জনাৰ কলা।\"",
|
||||
"settings.locale": "as",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} দল",
|
||||
"emails.sender": "%s দল",
|
||||
"emails.verification.subject": "একাউণ্ট প্ৰমাণীকৰণ",
|
||||
"emails.verification.hello": "নমস্কাৰ {{user}},",
|
||||
"emails.verification.hello": "নমস্কাৰ {{name}}",
|
||||
"emails.verification.body": "আপোনাৰ ইমেইল ঠিকনা প্ৰমাণিত কৰিবলৈ এই লিংকটো অনুসৰণ কৰক।",
|
||||
"emails.verification.footer": "যদি আপুনি এই ঠিকনাটো সত্যাপিত কৰিবলৈ কোৱা নাই, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।",
|
||||
"emails.verification.thanks": "ধন্যবাদ,",
|
||||
"emails.verification.buttonText": "ইমেইল ঠিকনা নিশ্চিত কৰক",
|
||||
"emails.verification.thanks": "ধন্যবাদ",
|
||||
"emails.verification.signature": "{{project}} দল",
|
||||
"emails.magicSession.subject": "লগইন",
|
||||
"emails.magicSession.hello": "নমস্কাৰ,",
|
||||
"emails.magicSession.thanks": "ধন্যবাদ,",
|
||||
"emails.magicSession.body": "লগইন কৰিবলৈ এই লিংকটো অনুসৰণ কৰক।",
|
||||
"emails.magicSession.footer": "যদি আপুনি এই ইমেইল ব্যৱহাৰ কৰি লগইন কৰিবলৈ কোৱা নাছিল, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।",
|
||||
"emails.magicSession.thanks": "ধন্যবাদ",
|
||||
"emails.magicSession.signature": "{{project}} দল",
|
||||
"emails.recovery.subject": "পাছৱাৰ্ড ৰিছেট",
|
||||
"emails.recovery.hello": "ধন্যবাদ {{user}},",
|
||||
"emails.recovery.hello": "ধন্যবাদ {{name}}",
|
||||
"emails.recovery.body": "আপোনাৰ {{project}} পাছৱৰ্ড ৰিছেট কৰিবলৈ এই লিংকটো অনুসৰণ কৰক।.",
|
||||
"emails.recovery.footer": "যদি আপুনি আপোনাৰ পাছৱৰ্ড ৰিছেট কৰিবলৈ কোৱা নাছিল, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।",
|
||||
"emails.recovery.thanks": "ধন্যবাদ,",
|
||||
"emails.recovery.buttonText": "পাছৱৰ্ড ৰিছেট কৰক",
|
||||
"emails.recovery.thanks": "ধন্যবাদ",
|
||||
"emails.recovery.signature": "{{project}} দল",
|
||||
"emails.invitation.subject": "{{team}} বছৰত {{project}} দললৈ নিমন্ত্ৰণ",
|
||||
"emails.invitation.hello": "নমস্কাৰ,",
|
||||
"emails.invitation.subject": "%s বছৰত %s দললৈ নিমন্ত্ৰণ",
|
||||
"emails.invitation.hello": "নমস্কাৰ",
|
||||
"emails.invitation.body": "এই মেইলটো আপোনালৈ প্ৰেৰণ কৰা হৈছিল কাৰণ {{owner}} জনে আপোনাক {{project}} বছৰবয়সত {{team}} দলৰ সদস্য হ'বলৈ আমন্ত্ৰণ জনাব বিচাৰিছিল।",
|
||||
"emails.invitation.footer": "যদি আপুনি আগ্ৰহী নহয়, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।",
|
||||
"emails.invitation.thanks": "ধন্যবাদ,",
|
||||
"emails.invitation.buttonText": "{{team}}-লৈ নিমন্ত্ৰণ গ্ৰহণ কৰক",
|
||||
"emails.invitation.thanks": "ধন্যবাদ",
|
||||
"emails.invitation.signature": "{{project}} দল",
|
||||
"locale.country.unknown": "অজ্ঞাত ",
|
||||
"countries.af": "আফগানিস্তান ",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "গ্ৰেনাডা",
|
||||
"countries.gt": "গুয়াতেমালা",
|
||||
"countries.gy": "গায়ানা",
|
||||
"countries.hk": "হং কং",
|
||||
"countries.hn": "হণ্ডুৰাছ",
|
||||
"countries.hr": "ক্ৰোৱেছিয়া",
|
||||
"countries.ht": "হাইতি",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "নিউজিলেণ্ড",
|
||||
"countries.om": "ওমান",
|
||||
"countries.pk": "পাকিস্তান",
|
||||
"countries.ps": "প্যালেস্টাইন",
|
||||
"countries.pa": "পানামা",
|
||||
"countries.pe": "পেৰু",
|
||||
"countries.ph": "ফিলিপাইনচ",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "টিউনিচিয়া",
|
||||
"countries.tr": "তুৰ্কী",
|
||||
"countries.tv": "টুভালু",
|
||||
"countries.tw": "তাইওয়ান",
|
||||
"countries.tz": "তাঞ্জানিয়া",
|
||||
"countries.ug": "উগাণ্ডা",
|
||||
"countries.ua": "ইউক্ৰেইন",
|
||||
@@ -232,24 +228,5 @@
|
||||
"continents.eu": "ইউৰোপ",
|
||||
"continents.na": "উত্তৰ আমেৰিকা",
|
||||
"continents.oc": "ওচেনিয়া",
|
||||
"continents.sa": "দক্ষিণ আমেৰিকা",
|
||||
"emails.magicSession.optionButton": "তলৰ বুটামটো ক্লিক কৰি আপোনাৰ {{project}} একাউণ্টত নিৰাপদে চাইন ইন কৰক। ই এঘণ্টাৰ ভিতৰত অবৈধ হ'ব।",
|
||||
"emails.magicSession.buttonText": "{{project}}ত প্ৰৱেশ কৰক",
|
||||
"emails.magicSession.optionUrl": "আপুনি ওপৰত দিয়া বুটাম ব্যৱহাৰ কৰি সাইন ইন কৰিব নোৱাৰিলে, অনুগ্ৰহ কৰি তলৰ লিংকটো ভ্ৰমণ কৰক:",
|
||||
"emails.magicSession.clientInfo": "এই চাইন ইনটো {{agentClient}} ব্যৱহাৰ কৰি {{agentDevice}} {{agentOs}}ত অনুৰোধ কৰা হৈছিল। আপুনি যদি চাইন ইনৰ অনুৰোধ নকৰা নাই, তেন্তে আপুনি এই ইমেইলখন নিৰাপদে উপেক্ষা কৰিব পাৰে।",
|
||||
"emails.magicSession.securityPhrase": "এই ইমেইলৰ বাবে নিরাপত্তা বাক্য হৈছে {{phrase}}। যদি এই বাক্যটো সাইন ইন কৰাৰ সময়ত দেখুওৱা বাক্যটোৰ সৈতে মিলে, তেন্তে আপুনি এই ইমেইলটোত বিশ্বাস কৰিব পাৰে।",
|
||||
"emails.otpSession.subject": "{{project}} লগইন",
|
||||
"emails.otpSession.hello": "নমস্কাৰ,",
|
||||
"emails.otpSession.description": "নিৰাপদে আপোনাৰ {{project}} একাউণ্টত চাইন ইন কৰাৰ সময়ত অনুৰোধ কৰা হ'লে তলৰ প্ৰমাণীকৰণ কোডটো প্ৰবেশ কৰক। ই ১৫ মিনিটত অবৈধ হৈ পৰিব।",
|
||||
"emails.otpSession.clientInfo": "এই চিনাক্তকৰণৰ অনুৰোধ {{agentClient}} ৰ জৰিয়তে {{agentDevice}} {{agentOs}} ত কৰা হৈছিল। আপুনি যদি চিনাক্তকৰণৰ অনুৰোধ কৰা নাই, তেন্তে আপুনি এই ইমেইলটো নিৰাপদে অগ্ৰাহ্য কৰিব পাৰে।",
|
||||
"emails.otpSession.securityPhrase": "এই ইমেইলৰ সুৰক্ষা বাক্যটো হৈছে {{phrase}}। আপুনি এই ইমেইলটোত আস্থা ৰাখিব পাৰে যদি প্ৰবেশৰ সময়ত দেখুৱাই থকা বাক্যটোৰ লগত এই বাক্যটো মেলে।",
|
||||
"emails.otpSession.thanks": "ধন্যবাদ,",
|
||||
"emails.otpSession.signature": "{{project}} দল",
|
||||
"emails.certificate.subject": "{{domain}}ৰ বাবে প্ৰমাণপত্ৰ ব্যৰ্থতা",
|
||||
"emails.certificate.hello": "নমস্কাৰ,",
|
||||
"emails.certificate.body": "আপোনাৰ ডোমেইন '{{domain}}' ৰ বাবে প্ৰমাণপত্ৰটো উত্পন্ন কৰিব পৰা নগ'ল। এয়া প্ৰচেষ্টা নম্বৰ {{attempt}}, আৰু বিফলতাৰ কাৰণ হ'ল: {{error}}",
|
||||
"emails.certificate.footer": "আপোনাৰ পূৰ্বৰ প্ৰমাণপত্ৰটো প্ৰথম ব্ৰিফল হোৱাৰ দিনৰ পৰা ৩০ দিনলৈ বৈধ থাকিব। আমি এই ঘটনাটোৰ তদন্ত কৰিবলৈ উচ্চ পৰামৰ্শ দিয়ে, অন্যথা আপোনাৰ ডোমেইনটো অবৈধ SSL যোগাযোগ অবিহনে থাকিব।",
|
||||
"emails.certificate.thanks": "ধন্যবাদ,",
|
||||
"emails.certificate.signature": "{{project}} দল",
|
||||
"sms.verification.body": "{{secret}}"
|
||||
}
|
||||
"continents.sa": "দক্ষিণ আমেৰিকা"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"Ağıllı olmaq sənəti, nəyi gözdən qaçıracağını bilmək sənətidir.\"",
|
||||
"settings.locale": "az",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Komandası",
|
||||
"emails.sender": "%s Komandası",
|
||||
"emails.verification.subject": "Hesab Doğrulama",
|
||||
"emails.verification.hello": "Salam {{user}},",
|
||||
"emails.verification.hello": "Salam {{name}}",
|
||||
"emails.verification.body": "E-poçt ünvanınızı təsdiq etmək üçün bu linki izləyin.",
|
||||
"emails.verification.footer": "Bu ünvanı doğrulamağı xahiş etməmisinizsə, bu mesajı gözardı edə bilərsiniz.",
|
||||
"emails.verification.thanks": "Təşəkkürlər,",
|
||||
"emails.verification.buttonText": "E-poçt ünvanını təsdiqlə",
|
||||
"emails.verification.thanks": "Təşəkkürlər",
|
||||
"emails.verification.signature": "{{project}} komandası",
|
||||
"emails.magicSession.subject": "Daxil Olmaq",
|
||||
"emails.magicSession.hello": "Salam,",
|
||||
"emails.magicSession.thanks": "Təşəkkürlər,",
|
||||
"emails.magicSession.body": "Daxil olmaq üçün bu linki izləyin.",
|
||||
"emails.magicSession.footer": "Bu e-poçtdan istifadə edərək giriş istəməmisinizsə, bu mesajı görməməzlikdən gələ bilərsiniz.",
|
||||
"emails.magicSession.thanks": "Təşəkkürlər",
|
||||
"emails.magicSession.signature": "{{project}} komandası",
|
||||
"emails.recovery.subject": "Şifrə Sıfırlanması",
|
||||
"emails.recovery.hello": "Salam {{user}},",
|
||||
"emails.recovery.hello": "Salam {{name}}",
|
||||
"emails.recovery.body": "{{project}} şifrənizi sıfırlamaq üçün bu linki izləyin.",
|
||||
"emails.recovery.footer": "Şifrənizi sıfırlamağı xahiş etməmisinizsə, bu mesajı gözardı edə bilərsiniz.",
|
||||
"emails.recovery.thanks": "Təşəkkürlər,",
|
||||
"emails.recovery.buttonText": "Şifrəni sıfırla",
|
||||
"emails.recovery.thanks": "Təşəkkürlər",
|
||||
"emails.recovery.signature": "{{project}} komandası",
|
||||
"emails.invitation.subject": "{{team}} Komandasına Dəvət {{project}}də",
|
||||
"emails.invitation.hello": "Salam,",
|
||||
"emails.invitation.subject": "%s Komandasına Dəvət %sdə",
|
||||
"emails.invitation.hello": "Salam",
|
||||
"emails.invitation.body": "{{owner}}, {{project}}də {{team}} komandasına üzv olmağa dəvət etmək istədiyi üçün bu məktub sizə göndərildi.",
|
||||
"emails.invitation.footer": "Əgər maraqlanmırsınızsa, bu mesajı gözardı edə bilərsiniz.",
|
||||
"emails.invitation.thanks": "Təşəkkürlər,",
|
||||
"emails.invitation.buttonText": "{{team}} dəvətini qəbul et",
|
||||
"emails.invitation.thanks": "Təşəkkürlər",
|
||||
"emails.invitation.signature": "{{project}} komandası",
|
||||
"locale.country.unknown": "Naməlum",
|
||||
"countries.af": "Əfqanıstan",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Qrenada",
|
||||
"countries.gt": "Qvatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Honq Konq",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Xorvatiya",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Yeni Zelandiya",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Fələstin",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Filippin",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Tunis",
|
||||
"countries.tr": "Türkiyə",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Tayvan",
|
||||
"countries.tz": "Tanzaniya",
|
||||
"countries.ug": "Uqanda",
|
||||
"countries.ua": "Ukrayna",
|
||||
@@ -225,25 +221,5 @@
|
||||
"countries.ye": "Yəmən",
|
||||
"countries.za": "Cənubi Afrika",
|
||||
"countries.zm": "Zambiya",
|
||||
"countries.zw": "Zimbabve",
|
||||
"emails.magicSession.optionButton": "Aşağıdaki düyməyə basaraq {{project}} hesabınıza təhlükəsiz şəkildə daxil olun. Bu, 1 saat sonra müddəti bitəcək.",
|
||||
"emails.magicSession.buttonText": "{{project}} layihəsinə daxil olun",
|
||||
"emails.magicSession.clientInfo": "Bu giriş, {{agentClient}} vasitəsi ilə {{agentDevice}} {{agentOs}} istifadə edərək tələb olunmuşdur. Əgər siz girişi tələb etməmisinizsə, bu e-poçtu təhlükəsiz şəkildə yoksayabilirsiniz.",
|
||||
"continents.af": "Afrika",
|
||||
"continents.an": "Antarktida",
|
||||
"continents.as": "Asiya",
|
||||
"continents.eu": "Avropa",
|
||||
"continents.na": "Şimali Amerika",
|
||||
"continents.oc": "Okeaniya",
|
||||
"continents.sa": "Cənubi Amerika",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Bu e-poçt üçün təhlükəsizlik ifadəsi {{phrase}}-dir. Əgər bu ifadə daxil olarkən göstərilən ifadə ilə üst-üstə düşürsə, bu e-poçta etibar edə bilərsiniz.",
|
||||
"emails.magicSession.optionUrl": "Əgər yuxarıdakı düyməni istifadə edərək daxil ola bilmirsizsə, zəhmət olmasa aşağıdakı linkə daxil olun:",
|
||||
"emails.otpSession.subject": "{{project}} Giriş",
|
||||
"emails.otpSession.hello": "Salam,",
|
||||
"emails.otpSession.description": "İstifadəçi tələb olunan zaman {{project}} hesabınıza təhlükəsiz daxil olmaq üçün aşağıdakı təsdiqləmə kodunu daxil edin. Bu kod 15 dəqiqə sonra etibarsız olacaq.",
|
||||
"emails.otpSession.clientInfo": "Bu giriş {{agentClient}} vasitəsilə {{agentDevice}} {{agentOs}} istifadə edərək istənildi. Əgər siz giriş istəməmisinizsə, bu e-poçtu laqeyd qoya bilərsiniz.",
|
||||
"emails.otpSession.securityPhrase": "Bu e-poçtun təhlükəsizlik ifadəsi {{phrase}}-dir. Əgər bu ifadə daxil olarkən göstərilən ifadə ilə üst-üstə düşürsə, bu e-poçta etibar edə bilərsiniz.",
|
||||
"emails.otpSession.thanks": "Sağ olun,",
|
||||
"emails.otpSession.signature": "{{project}} komandası"
|
||||
"countries.zw": "Zimbabve"
|
||||
}
|
||||
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"Мастацтва быць мудрым - гэта мастацтва ведаць, на што нельга звярнуць увагу.\"",
|
||||
"settings.locale": "be",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "Каманда {{project}}",
|
||||
"emails.sender": "Каманда %s",
|
||||
"emails.verification.subject": "Верыфікацыя акаўнта",
|
||||
"emails.verification.hello": "Прывітанне {{user}},",
|
||||
"emails.verification.hello": "Прывітанне {{name}}",
|
||||
"emails.verification.body": "Перайдзіце па гэтай спасылцы, каб пацвердзіць свой адрас электроннай пошты",
|
||||
"emails.verification.footer": "Калі вы не запытвалі пацвярджэнне гэтага адрасу, праігнаруйце гэтае паведамленне.",
|
||||
"emails.verification.thanks": "Дзякуем,",
|
||||
"emails.verification.buttonText": "Пацвердзіць адрас электроннай пошты",
|
||||
"emails.verification.thanks": "Дзякуем",
|
||||
"emails.verification.signature": "каманда {{project}}",
|
||||
"emails.magicSession.subject": "Лагін",
|
||||
"emails.magicSession.hello": "Прывітанне,",
|
||||
"emails.magicSession.thanks": "Дзякуем,",
|
||||
"emails.magicSession.body": "Перайдзіце па спасылцы, каб увайсці.",
|
||||
"emails.magicSession.footer": "Калі вы не прасілі ўвайсці, выкарыстоўваючы гэты адрас электроннай пошты, праігнаруйце гэтае паведамленне.",
|
||||
"emails.magicSession.thanks": "Дзякуем",
|
||||
"emails.magicSession.signature": "каманда {{project}}",
|
||||
"emails.recovery.subject": "Скід пароля",
|
||||
"emails.recovery.hello": "Прывітанне, {{user}},",
|
||||
"emails.recovery.hello": "Прывітанне, {{name}}",
|
||||
"emails.recovery.body": "Перайдзіце па гэтай спасылцы, каб скінуць пароль для праекта {{project}}.",
|
||||
"emails.recovery.footer": "Калі вы не прасілі скінуць пароль, вы можаце праігнараваць гэта паведамленне.",
|
||||
"emails.recovery.thanks": "Дзякуем,",
|
||||
"emails.recovery.buttonText": "Аднавіць пароль",
|
||||
"emails.recovery.thanks": "Дзякуем",
|
||||
"emails.recovery.signature": "каманда {{project}}",
|
||||
"emails.invitation.subject": "Запрошення до Команди {{team}} у {{project}}",
|
||||
"emails.invitation.hello": "Прывітанне,",
|
||||
"emails.invitation.subject": "Запрошення до Команди %s у %s",
|
||||
"emails.invitation.hello": "Прывітанне",
|
||||
"emails.invitation.body": "Гэта паведамленне было адпраўлена вам, таму што {{owner}} хацеў запрасіць вас стаць членам каманды {{team}} у {{project}}.",
|
||||
"emails.invitation.footer": "Калі вам гэта не цікава, вы можаце праігнараваць гэтае паведамленне.",
|
||||
"emails.invitation.thanks": "Дзякуем,",
|
||||
"emails.invitation.buttonText": "Прыняць запрашэнне ў {{team}}",
|
||||
"emails.invitation.thanks": "Дзякуем",
|
||||
"emails.invitation.signature": "каманда {{project}}",
|
||||
"locale.country.unknown": "Невядомы",
|
||||
"countries.af": "Афганістан",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Грэнада",
|
||||
"countries.gt": "Гватэмала",
|
||||
"countries.gy": "Гаяна",
|
||||
"countries.hk": "Гонконг",
|
||||
"countries.hn": "Гандурас",
|
||||
"countries.hr": "Харватыя",
|
||||
"countries.ht": "Гаіці",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Новая Зеландыя",
|
||||
"countries.om": "Аман",
|
||||
"countries.pk": "Пакістан",
|
||||
"countries.ps": "Палестина",
|
||||
"countries.pa": "Панама",
|
||||
"countries.pe": "Перу",
|
||||
"countries.ph": "Філіпіны",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Туніс",
|
||||
"countries.tr": "Турцыя",
|
||||
"countries.tv": "Тувалу",
|
||||
"countries.tw": "Тайвань",
|
||||
"countries.tz": "Танзанія",
|
||||
"countries.ug": "Уганда",
|
||||
"countries.ua": "Украіна",
|
||||
@@ -232,24 +228,5 @@
|
||||
"continents.eu": "Еўропа",
|
||||
"continents.na": "Паўночная Амерыка",
|
||||
"continents.oc": "Акіянія",
|
||||
"continents.sa": "Паўднёвая Амерыка",
|
||||
"emails.magicSession.optionButton": "Націсніце кнопку ніжэй, каб бяспечна ўвайсці ў свой рахунак {{project}}. Яна спыніць дзеянне праз 1 гадзіну.",
|
||||
"emails.magicSession.buttonText": "Увайдзіце ў {{project}}",
|
||||
"emails.magicSession.optionUrl": "Калі ў вас не атрымліваецца ўвайсці, выкарыстоўваючы кнопку вышэй, калі ласка, наведайце наступную спасылку:",
|
||||
"emails.magicSession.clientInfo": "Гэты ўваход быў запытаны праз {{agentClient}} на {{agentDevice}} {{agentOs}}. Калі вы не запытвалі ўваход, вы можаце бяспечна ігнараваць гэты ліст.",
|
||||
"emails.magicSession.securityPhrase": "Фраза бяспекі для гэтага ліста - {{phrase}}. Вы можаце давяраць гэтаму лісту, калі гэтая фраза супадае з фразай, якая была паказана пры ўваходзе ў сістэму.",
|
||||
"emails.otpSession.subject": "{{project}} Уваход",
|
||||
"emails.otpSession.hello": "Прывітанне,",
|
||||
"emails.otpSession.description": "Увядзіце наступны код пацверджання, калі будзеце запытаны, каб бяспечна ўвайсці ў ваш уліковы запіс {{project}}. Ён страціць сілу праз 15 хвілін.",
|
||||
"emails.otpSession.clientInfo": "Гэты ўваход быў запытаны пры дапамозе {{agentClient}} на {{agentDevice}} {{agentOs}}. Калі вы не запытвалі ўваход, вы можаце бяспечна ігнараваць гэты ліст.",
|
||||
"emails.otpSession.securityPhrase": "Фраза бяспекі для гэтага ліста - {{phrase}}. Вы можаце давяраць гэтаму лісту, калі гэтая фраза супадае з фразай, паказанай пры ўваходзе.",
|
||||
"emails.otpSession.thanks": "Дзякуй,",
|
||||
"emails.otpSession.signature": "каманда {{project}}",
|
||||
"emails.certificate.subject": "Сведчанне няўдалае для {{domain}}",
|
||||
"emails.certificate.hello": "Прывітанне,",
|
||||
"emails.certificate.body": "Сертыфікат для вашага дамена '{{domain}}' не можа быць створаны. Гэта спроба нумар {{attempt}}, і прычынай няўдачы з'яўляецца: {{error}}",
|
||||
"emails.certificate.footer": "Ваш папярэдні сертыфікат будзе дзейнічаць 30 дзён з моманту першай няўдачы. Мы высока рэкамендуем расследаваць гэтую сітуацыю, інакш ваш дамен апынецца без дзейнага сертыфіката SSL-злучэння.",
|
||||
"emails.certificate.thanks": "Дзякуй,",
|
||||
"emails.certificate.signature": "каманда {{project}}",
|
||||
"sms.verification.body": "{{secret}}"
|
||||
"continents.sa": "Паўднёвая Амерыка"
|
||||
}
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
"settings.inspire": "\"Изкуството да бъдеш мъдър е изкуството да знаеш какво да пренебрегнеш.\"",
|
||||
"settings.locale": "bg",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Екип",
|
||||
"emails.sender": "%s Екип",
|
||||
"emails.verification.subject": "",
|
||||
"emails.verification.hello": ",",
|
||||
"emails.verification.hello": "",
|
||||
"emails.verification.body": "",
|
||||
"emails.verification.footer": "",
|
||||
"emails.verification.thanks": ",",
|
||||
"emails.verification.thanks": "",
|
||||
"emails.verification.signature": "",
|
||||
"emails.magicSession.subject": "",
|
||||
"emails.magicSession.hello": ",",
|
||||
"emails.magicSession.thanks": ",",
|
||||
"emails.magicSession.hello": "",
|
||||
"emails.magicSession.body": "",
|
||||
"emails.magicSession.footer": "",
|
||||
"emails.magicSession.thanks": "",
|
||||
"emails.magicSession.signature": "",
|
||||
"emails.recovery.subject": "",
|
||||
"emails.recovery.hello": ",",
|
||||
"emails.recovery.hello": "",
|
||||
"emails.recovery.body": "",
|
||||
"emails.recovery.footer": "",
|
||||
"emails.recovery.thanks": ",",
|
||||
"emails.recovery.thanks": "",
|
||||
"emails.recovery.signature": "",
|
||||
"emails.invitation.subject": "",
|
||||
"emails.invitation.hello": ",",
|
||||
"emails.invitation.hello": "",
|
||||
"emails.invitation.body": "",
|
||||
"emails.invitation.footer": "",
|
||||
"emails.invitation.thanks": ",",
|
||||
"emails.invitation.thanks": "",
|
||||
"emails.invitation.signature": "",
|
||||
"locale.country.unknown": "Неизвестно",
|
||||
"countries.af": "Афганистан",
|
||||
@@ -98,7 +100,6 @@
|
||||
"countries.gd": "Гренада",
|
||||
"countries.gt": "Гватемала",
|
||||
"countries.gy": "Гвиана",
|
||||
"countries.hk": "Хонг Конг",
|
||||
"countries.hn": "Хондурас",
|
||||
"countries.hr": "Хърватия",
|
||||
"countries.ht": "Хаити",
|
||||
@@ -162,7 +163,6 @@
|
||||
"countries.nz": "Нова Зеландия",
|
||||
"countries.om": "Оман",
|
||||
"countries.pk": "Пакистан",
|
||||
"countries.ps": "Палестина",
|
||||
"countries.pa": "Панама",
|
||||
"countries.pe": "Перу",
|
||||
"countries.ph": "Филипини",
|
||||
@@ -206,7 +206,6 @@
|
||||
"countries.tn": "Тунис",
|
||||
"countries.tr": "Турция",
|
||||
"countries.tv": "Тувалу",
|
||||
"countries.tw": "Тайван",
|
||||
"countries.tz": "Танзания",
|
||||
"countries.ug": "Уганда",
|
||||
"countries.ua": "Украйна",
|
||||
@@ -229,18 +228,5 @@
|
||||
"continents.eu": "Европа",
|
||||
"continents.na": "Северна Америка",
|
||||
"continents.oc": "Океания",
|
||||
"continents.sa": "Южна Америка",
|
||||
"emails.magicSession.optionButton": "Натиснете бутона по-долу, за да се впишете сигурно във вашия {{project}} акаунт. Той ще изтече след 1 час.",
|
||||
"emails.magicSession.buttonText": "Влезте в {{project}}",
|
||||
"emails.magicSession.clientInfo": "Този вход беше заявен чрез {{agentClient}} на {{agentDevice}} {{agentOs}}. Ако не сте поискали входа, можете безопасно да игнорирате този имейл.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Фразата за сигурност на този имейл е {{phrase}}. Можете да се доверите на този имейл, ако тази фраза съвпада с фразата, показана по време на вписването.",
|
||||
"emails.magicSession.optionUrl": "Ако не можете да влезете чрез горния бутон, моля, посетете следния линк:",
|
||||
"emails.otpSession.subject": "Вход в {{project}}",
|
||||
"emails.otpSession.hello": "Здравейте,",
|
||||
"emails.otpSession.description": "Въведете следния верификационен код, когато ви бъде поискано, за да се впишете сигурно в своята {{project}} сметка. Ще изтече след 15 минути.",
|
||||
"emails.otpSession.clientInfo": "Този вход беше заявен чрез {{agentClient}} на {{agentDevice}} {{agentOs}}. Ако не сте заявили входа, можете спокойно да пренебрегнете този имейл.",
|
||||
"emails.otpSession.securityPhrase": "Фразата за сигурност за този имейл е {{phrase}}. Можете да се доверите на този имейл, ако тази фраза съвпада с фразата, показана по време на вписването.",
|
||||
"emails.otpSession.thanks": "Благодаря,",
|
||||
"emails.otpSession.signature": "екип на {{project}}"
|
||||
}
|
||||
"continents.sa": "Южна Америка"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"बुद्धिमान होइत क कला ई जाने क कला अछि जे की अनदेखा कर्मा चाहि| \"",
|
||||
"settings.locale": "bh",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} टीम",
|
||||
"emails.sender": "%s टीम",
|
||||
"emails.verification.subject": "खाता प्रमाणिकरण",
|
||||
"emails.verification.hello": "नमस्ते {{user}},",
|
||||
"emails.verification.hello": "नमस्ते {{name}}",
|
||||
"emails.verification.body": "ईमेल प्रमाणिकरण करे क लेल दिहल गइल लिंक फॉलो करें|",
|
||||
"emails.verification.footer": "अगर ई पता को सत्यापित करे के लिए ना कहाले, तो आप ई संदेश क अनदेखा कर सकत अछि।",
|
||||
"emails.verification.thanks": "धन्यवाद,",
|
||||
"emails.verification.buttonText": "ईमेल पता के पुष्टि करीं",
|
||||
"emails.verification.thanks": "धन्यवाद",
|
||||
"emails.verification.signature": "{{project}} टीम",
|
||||
"emails.magicSession.subject": "लॉग इन करीं|",
|
||||
"emails.magicSession.hello": "प्रणाम,",
|
||||
"emails.magicSession.thanks": "धन्यवाद,",
|
||||
"emails.magicSession.hello": "प्रणाम",
|
||||
"emails.magicSession.body": "लॉग इन करें लेल दिहल गइल लिंक फॉलो करें|",
|
||||
"emails.magicSession.footer": "अगर लॉग इन करे के लिए ना कहाले, तो आप ई संदेश क अनदेखा कर सकत अछि।",
|
||||
"emails.magicSession.thanks": "धन्यवाद",
|
||||
"emails.magicSession.signature": "{{project}} टीम",
|
||||
"emails.recovery.subject": "पासवर्ड बदल क लेल|",
|
||||
"emails.recovery.hello": "प्रणाम {{user}},",
|
||||
"emails.recovery.hello": "प्रणाम {{name}}",
|
||||
"emails.recovery.body": "पासवर्ड बदल क लेल दिहल गइल लिंक फॉलो करें|",
|
||||
"emails.recovery.footer": "अगर पासवर्ड बदल क लेल ना कहाले, तो आप ई संदेश क अनदेखा कर सकत अछि।",
|
||||
"emails.recovery.thanks": "धन्यवाद,",
|
||||
"emails.recovery.buttonText": "पासवर्ड रीसेट करीं",
|
||||
"emails.recovery.thanks": "धन्यवाद",
|
||||
"emails.recovery.signature": "{{project}} टीम",
|
||||
"emails.invitation.subject": "{{team}} टीम क {{project}} पे न्योता देवे क लेल|",
|
||||
"emails.invitation.hello": "प्रणाम,",
|
||||
"emails.invitation.subject": "%s टीम क %s पे न्योता देवे क लेल|",
|
||||
"emails.invitation.hello": "प्रणाम",
|
||||
"emails.invitation.body": "ई मेल आपके एही लेल भेजल गईल रहल काहे क {{owner}} आपके {{project}} क {{team}} टीम का सदस्य बनावे चाहित रहे|",
|
||||
"emails.invitation.footer": "अगर आवे क इच्छा ना होवत, तो आप ई संदेश क अनदेखा कर सकत अछि।",
|
||||
"emails.invitation.thanks": "धन्यवाद,",
|
||||
"emails.invitation.buttonText": "{{team}} में नेवता स्वीकार करीं",
|
||||
"emails.invitation.thanks": "धन्यवाद",
|
||||
"emails.invitation.signature": "{{project}} टीम",
|
||||
"locale.country.unknown": "अनजान",
|
||||
"countries.af": "अफ़ग़ानिस्तान",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "ग्रेनाडा",
|
||||
"countries.gt": "ग्वाटेमाला",
|
||||
"countries.gy": "गयाना",
|
||||
"countries.hk": "हांगकांग",
|
||||
"countries.hn": "होंडुरस",
|
||||
"countries.hr": "क्रोएशिया",
|
||||
"countries.ht": "हैती",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "न्यूजीलैंड",
|
||||
"countries.om": "ओमान",
|
||||
"countries.pk": "पाकिस्तान",
|
||||
"countries.ps": "पैलिस्टाइन",
|
||||
"countries.pa": "पनामा",
|
||||
"countries.pe": "पेरू",
|
||||
"countries.ph": "फिलीपींस",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "ट्यूनीशिया",
|
||||
"countries.tr": "तुर्की",
|
||||
"countries.tv": "तुवालू",
|
||||
"countries.tw": "ताइवान",
|
||||
"countries.tz": "तंजानिया",
|
||||
"countries.ug": "युगांडा",
|
||||
"countries.ua": "यूक्रेन",
|
||||
@@ -232,24 +228,5 @@
|
||||
"continents.eu": "यूरोप",
|
||||
"continents.na": "उत्तरी अमेरिका",
|
||||
"continents.oc": "ओशिनिया",
|
||||
"continents.sa": "दक्षिण अमेरिका",
|
||||
"emails.magicSession.optionButton": "नीचा देल बटन पर क्लिक करीं अपना {{project}} खाता में सुरक्षित रूप से साइन इन करे खातिर। ई 1 घंटा में समाप्त हो जाई।",
|
||||
"emails.magicSession.buttonText": "{{project}} में साइन इन करीं",
|
||||
"emails.magicSession.optionUrl": "अगर रउआ उपरका बटन से साइन इन ना कर पाईं तs, कृपया निचे दिहल लिंक पर जाई:",
|
||||
"emails.magicSession.clientInfo": "ई साइन इन अनुरोध किया गेल {{agentClient}} पर {{agentDevice}} {{agentOs}} पर. यदि अहाँ एहि साइन इन के अनुरोध नै कइनी होखी तs अहाँ ई ईमेल के अनदेखा क सकऽ छी.",
|
||||
"emails.magicSession.securityPhrase": "एह ईमेल खातिर सुरक्षा वाक्य {{phrase}} हऽ। ई ईमेल पर भरोसा करीं जदि ई वाक्य साइन इन करत समय देखावल वाक्य से मिलता हो।",
|
||||
"emails.otpSession.subject": "प्रोजेक्ट लॉगिन",
|
||||
"emails.otpSession.hello": "नमस्ते,",
|
||||
"emails.otpSession.description": "जब आपको सुरक्षित रूप से अपना {{project}} खाता में साइन इन करे खातिर कहल जाए तऽ निम्नलिखित सत्यापन कोड दर्ज करीं। ई 15 मिनट में खत्म हो जई।",
|
||||
"emails.otpSession.clientInfo": "एह साइन इन के अनुरोध {{agentClient}} पर {{agentDevice}} {{agentOs}} का प्रयोग करि कऽ कइल गइल बा। यदि तूँ एह साइन इन के अनुरोध ना कइले रहीं, त तूँ एह ईमेल के नजरअंदाज कर सकेला।",
|
||||
"emails.otpSession.securityPhrase": "एही ईमेल खातिर सुरक्षा वाक्य {{phrase}} हऽ। अगर ई वाक्य साइन इन कइला के समय देखावल गेल वाक्य से मेल खाता, त एह ईमेल पर भरोसा कर सकैत छी।",
|
||||
"emails.otpSession.thanks": "धन्यवाद,",
|
||||
"emails.otpSession.signature": "{{project}} टीम",
|
||||
"emails.certificate.subject": "{{domain}} लेल प्रमाणपत्र असफलता",
|
||||
"emails.certificate.hello": "नमस्ते,",
|
||||
"emails.certificate.body": "आपके डोमेन '{{domain}}' के लिए प्रमाणपत्र नहीं बनाया जा सका। ई प्रयास संख्या {{attempt}} है, और ई असफलता के कारण रहे: {{error}}",
|
||||
"emails.certificate.footer": "तोहार पिछलका प्रमाणपत्र पहिल असफलता से 30 दिन धरी मान्य होईत। हम बहुत जोर देके सलाह देतानी कि एह मामला के जांच करीं, नहीं त तोहार डोमेन बिना कोनो मान्य SSL संवाद के रहि जाईत।",
|
||||
"emails.certificate.thanks": "धन्यवाद,",
|
||||
"emails.certificate.signature": "{{project}} टीम",
|
||||
"sms.verification.body": "{{secret}}"
|
||||
}
|
||||
"continents.sa": "दक्षिण अमेरिका"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"জ্ঞানী হওয়ার শিল্প হলো কোন বিষয়টিকে উপেক্ষা করা উচিত তা জানার শিল্প\"",
|
||||
"settings.locale": "bn",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} টীম",
|
||||
"emails.sender": "%s টীম",
|
||||
"emails.verification.subject": "বিষয়",
|
||||
"emails.verification.hello": "নমস্কার {{user}},",
|
||||
"emails.verification.hello": "নমস্কার {{name}}",
|
||||
"emails.verification.body": "এই লিঙ্কের মাধ্যমে ইমেইল যাচাই করুন।",
|
||||
"emails.verification.footer": "আপনি যদি এই ঠিকানা যাচাই করতে না বলেন, তাহলে আপনি এই বার্তাটি উপেক্ষা করতে পারেন।",
|
||||
"emails.verification.thanks": "ধন্যবাদ,",
|
||||
"emails.verification.buttonText": "ইমেইল ঠিকানা নিশ্চিত করুন",
|
||||
"emails.verification.thanks": "ধন্যবাদ",
|
||||
"emails.verification.signature": "{{project}} টীম",
|
||||
"emails.magicSession.subject": "লগ ইন",
|
||||
"emails.magicSession.hello": "নমস্কার,",
|
||||
"emails.magicSession.thanks": "ধন্যবাদ,",
|
||||
"emails.magicSession.hello": "নমস্কার",
|
||||
"emails.magicSession.body": "এই লিঙ্কের মাধ্যমে লগ ইন করুন।",
|
||||
"emails.magicSession.footer": "আপনি যদি এই ইমেলটি ব্যবহার করে লগইন করতে না বলেন, তাহলে আপনি এই বার্তাটি উপেক্ষা করতে পারেন।",
|
||||
"emails.magicSession.thanks": "ধন্যবাদ",
|
||||
"emails.magicSession.signature": "{{project}} টীম",
|
||||
"emails.recovery.subject": "পাসওয়ার্ড রিসেট",
|
||||
"emails.recovery.hello": "নমস্কার {{user}},",
|
||||
"emails.recovery.hello": "নমস্কার {{name}}",
|
||||
"emails.recovery.body": "এই লিঙ্কের মাধ্যমে আপনার {{project}} পাসওয়ার্ড পুনরায় সেট করুন।",
|
||||
"emails.recovery.footer": "আপনি যদি আপনার পাসওয়ার্ড পুনরায় সেট করতে না বলেন, তাহলে আপনি এই বার্তাটি উপেক্ষা করতে পারেন।",
|
||||
"emails.recovery.thanks": "ধন্যবাদ,",
|
||||
"emails.recovery.buttonText": "পাসওয়ার্ড রিসেট করুন",
|
||||
"emails.recovery.thanks": "ধন্যবাদ",
|
||||
"emails.recovery.signature": "{{project}} টীম",
|
||||
"emails.invitation.subject": "{{team}} টিমকে {{project}} তে আমন্ত্রণ জানান",
|
||||
"emails.invitation.hello": "নমস্কার,",
|
||||
"emails.invitation.subject": "%s টিমকে %s তে আমন্ত্রণ জানান",
|
||||
"emails.invitation.hello": "নমস্কার",
|
||||
"emails.invitation.body": "এই মেইলটি আপনাকে পাঠানো হয়েছে কারণ {{owner}} আপনাকে {{project}} এর সাথে যুক্ত {{team}} টিমের সদস্য হওয়ার জন্য আমন্ত্রণ জানাতে চেয়েছিলেন।",
|
||||
"emails.invitation.footer": "যদি এটি আপনার জন্য প্রয়োজনীয় না হয়, আপনি এই বার্তাটি উপেক্ষা করতে পারেন।",
|
||||
"emails.invitation.thanks": "ধন্যবাদ,",
|
||||
"emails.invitation.buttonText": "{{team}}-এর আমন্ত্রণ গ্রহণ করুন",
|
||||
"emails.invitation.thanks": "ধন্যবাদ",
|
||||
"emails.invitation.signature": "{{project}} টীম",
|
||||
"locale.country.unknown": "অজানা",
|
||||
"countries.af": "আফগানিস্তান",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "গ্রেনাডা",
|
||||
"countries.gt": "গুয়াতেমালা",
|
||||
"countries.gy": "গায়ানা",
|
||||
"countries.hk": "হংকং",
|
||||
"countries.hn": "হন্ডুরাস",
|
||||
"countries.hr": "ক্রোয়েশিয়া",
|
||||
"countries.ht": "হাইতি",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "নিউজিল্যান্ড",
|
||||
"countries.om": "ওমান",
|
||||
"countries.pk": "পাকিস্তান",
|
||||
"countries.ps": "প্যালেস্টাইন",
|
||||
"countries.pa": "পানামা",
|
||||
"countries.pe": "পেরু",
|
||||
"countries.ph": "ফিলিপাইন",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "তিউনিসিয়া",
|
||||
"countries.tr": "তুরস্ক",
|
||||
"countries.tv": "টুভালু",
|
||||
"countries.tw": "তাইওয়ান",
|
||||
"countries.tz": "তানজানিয়া",
|
||||
"countries.ug": "উগান্ডা",
|
||||
"countries.ua": "ইউক্রেন",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "ইউরোপ",
|
||||
"continents.na": "উত্তর আমেরিকা",
|
||||
"continents.oc": "ওশেনিয়া",
|
||||
"continents.sa": "দক্ষিণ আমেরিকা",
|
||||
"emails.magicSession.optionButton": "নীচের বোতামে ক্লিক করুন আপনার {{project}} অ্যাকাউন্টে নিরাপদে সাইন ইন করতে। এটি ১ ঘন্টা পরে মেয়াদ উত্তীর্ণ হবে।",
|
||||
"emails.magicSession.buttonText": "{{project}}-এ সাইন ইন করুন",
|
||||
"emails.magicSession.clientInfo": "এই সাইন ইনটি {{agentClient}} ব্যবহার করে {{agentDevice}} {{agentOs}}-এ অনুরোধ করা হয়েছিল। যদি আপনি সাইন ইনের অনুরোধ করেননি, আপনি নিরাপদে এই ইমেইলটি উপেক্ষা করতে পারেন।",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "এই ইমেলের জন্য নিরাপত্তা বাক্যটি হল {{phrase}}। সাইন-ইনের সময় দেখানো বাক্যটির সাথে এই বাক্যটি মিলে গেলে আপনি এই ইমেইলকে বিশ্বাস করতে পারেন।",
|
||||
"emails.magicSession.optionUrl": "উপরের বোতামটি ব্যবহার করে আপনি যদি সাইন ইন করতে অক্ষম হন, অনুগ্রহ করে নিম্নলিখিত লিঙ্কটি দেখুন:",
|
||||
"emails.otpSession.subject": "{{project}} লগইন",
|
||||
"emails.otpSession.hello": "নমস্কার,",
|
||||
"emails.otpSession.description": "নিরাপদে আপনার {{project}} অ্যাকাউন্টে সাইন ইন করার জন্য যখন বলা হবে, তখন নিম্নলিখিত যাচাইকরণ কোডটি প্রবেশ করান। এটি ১৫ মিনিটের মধ্যে মেয়াদোত্তীর্ণ হয়ে যাবে।",
|
||||
"emails.otpSession.clientInfo": "এই সাইন ইনটি {{agentClient}} ব্যবহার করে {{agentDevice}} {{agentOs}}-এ অনুরোধ করা হয়েছে। আপনি যদি সাইন ইনের অনুরোধ না করে থাকেন, আপনি নিরাপদে এই ইমেলটি উপেক্ষা করতে পারেন।",
|
||||
"emails.otpSession.securityPhrase": "এই ইমেইলের জন্য সুরক্ষা বাক্য হলো {{phrase}}। যদি এই বাক্যটি সাইন ইনের সময় দেখানো বাক্যের সাথে মেলে, তাহলে আপনি এই ইমেইলটিকে বিশ্বাস করতে পারেন।",
|
||||
"emails.otpSession.thanks": "ধন্যবাদ,",
|
||||
"emails.otpSession.signature": "{{project}} দল"
|
||||
"continents.sa": "দক্ষিণ আমেরিকা"
|
||||
}
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
"settings.inspire": "\"Umjetnost mudrosti je umjetnost znanja o tome šta zanemariti.\"",
|
||||
"settings.locale": "bs",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Tim",
|
||||
"emails.sender": "%s Tim",
|
||||
"emails.verification.subject": "",
|
||||
"emails.verification.hello": ",",
|
||||
"emails.verification.hello": "",
|
||||
"emails.verification.body": "",
|
||||
"emails.verification.footer": "",
|
||||
"emails.verification.thanks": ",",
|
||||
"emails.verification.thanks": "",
|
||||
"emails.verification.signature": "",
|
||||
"emails.magicSession.subject": "",
|
||||
"emails.magicSession.hello": ",",
|
||||
"emails.magicSession.thanks": ",",
|
||||
"emails.magicSession.hello": "",
|
||||
"emails.magicSession.body": "",
|
||||
"emails.magicSession.footer": "",
|
||||
"emails.magicSession.thanks": "",
|
||||
"emails.magicSession.signature": "",
|
||||
"emails.recovery.subject": "",
|
||||
"emails.recovery.hello": ",",
|
||||
"emails.recovery.hello": "",
|
||||
"emails.recovery.body": "",
|
||||
"emails.recovery.footer": "",
|
||||
"emails.recovery.thanks": ",",
|
||||
"emails.recovery.thanks": "",
|
||||
"emails.recovery.signature": "",
|
||||
"emails.invitation.subject": "",
|
||||
"emails.invitation.hello": ",",
|
||||
"emails.invitation.hello": "",
|
||||
"emails.invitation.body": "",
|
||||
"emails.invitation.footer": "",
|
||||
"emails.invitation.thanks": ",",
|
||||
"emails.invitation.thanks": "",
|
||||
"emails.invitation.signature": "",
|
||||
"locale.country.unknown": "Nepoznat",
|
||||
"countries.af": "Afganistan",
|
||||
@@ -98,7 +100,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Gvajana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Hrvatska",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -162,7 +163,6 @@
|
||||
"countries.nz": "Novi Zeland",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palestina",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Filipini",
|
||||
@@ -206,7 +206,6 @@
|
||||
"countries.tn": "Tunis",
|
||||
"countries.tr": "Turska",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Tajvan",
|
||||
"countries.tz": "Tanzania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukrajina",
|
||||
@@ -229,18 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "Sjeverna Amerika",
|
||||
"continents.oc": "Okeanija",
|
||||
"continents.sa": "Južna Amerika",
|
||||
"emails.magicSession.optionButton": "Kliknite na dugme ispod kako biste se sigurno prijavili na svoj {{project}} račun. Istek će se dogoditi za 1 sat.",
|
||||
"emails.magicSession.buttonText": "Prijavi se na {{project}}",
|
||||
"emails.magicSession.clientInfo": "Ova prijava je zatražena korištenjem {{agentClient}} na {{agentDevice}} {{agentOs}}. Ako niste zahtjevali prijavu, možete sigurno ignorirati ovaj e-mail.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Sigurnosna fraza za ovaj email je {{phrase}}. Ovom emailu možete vjerovati ako se fraza poklapa sa frazom prikazanom prilikom prijave.",
|
||||
"emails.magicSession.optionUrl": "Ako ne možete da se prijavite koristeći gornje dugme, molimo posetite sledeći link:",
|
||||
"emails.otpSession.subject": "{{project}} Prijava",
|
||||
"emails.otpSession.hello": "Zdravo,",
|
||||
"emails.otpSession.description": "Unesite sljedeći verifikacijski kod kada budete upitani kako biste sigurno pristupili vašem {{project}} računu. Istjeći će za 15 minuta.",
|
||||
"emails.otpSession.clientInfo": "Ovaj zahtjev za prijavom je poslan koristeći {{agentClient}} na {{agentDevice}} {{agentOs}}. Ako niste zatražili prijavu, možete sigurno ignorisati ovaj email.",
|
||||
"emails.otpSession.securityPhrase": "Sigurnosna fraza za ovaj email je {{phrase}}. Možete vjerovati ovom emailu ako se ova fraza podudara sa frazom prikazanom prilikom prijave.",
|
||||
"emails.otpSession.thanks": "Hvala,",
|
||||
"emails.otpSession.signature": "tim {{project}}"
|
||||
}
|
||||
"continents.sa": "Južna Amerika"
|
||||
}
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"L'art de ser savi és l'art de saber què passar per alt\"",
|
||||
"settings.locale": "ca",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Equip",
|
||||
"emails.sender": "%s Equip",
|
||||
"emails.verification.subject": "Verificació del compte",
|
||||
"emails.verification.hello": "Hola {{user}},",
|
||||
"emails.verification.hello": "Hola {{name}}",
|
||||
"emails.verification.body": "Accedeix a aquest enllaç per tal de verificar la teva adreça electrònica.",
|
||||
"emails.verification.footer": "Si no has sol·licitat la verificació d'aquesta adreça electrònica, pots ignorar aquest missatge.",
|
||||
"emails.verification.thanks": "Gràcies,",
|
||||
"emails.verification.buttonText": "Confirma l'adreça electrònica",
|
||||
"emails.verification.thanks": "Gràcies",
|
||||
"emails.verification.signature": "Equip {{project}}",
|
||||
"emails.magicSession.subject": "Entrar",
|
||||
"emails.magicSession.hello": "Hola,",
|
||||
"emails.magicSession.thanks": "Gràcies,",
|
||||
"emails.magicSession.body": "Accedeix a aquest enllaç per a entrar.",
|
||||
"emails.magicSession.footer": "Si no has sol·licitat entrar amb aquesta adreça electrònica, pots ignorar aquest missatge.",
|
||||
"emails.magicSession.thanks": "Gràcies",
|
||||
"emails.magicSession.signature": "Equip {{project}}",
|
||||
"emails.recovery.subject": "Reinicialitzar contrasenya",
|
||||
"emails.recovery.hello": "Hola {{user}},",
|
||||
"emails.recovery.hello": "Hola {{name}}",
|
||||
"emails.recovery.body": "Accedeix a aquest enllaç per a reinicialitzar la teva contrasenya de {{project}}.",
|
||||
"emails.recovery.footer": "Si no has sol·licitat reinicialitzar la teva contrasenya, pots ignorar aquest missatge.",
|
||||
"emails.recovery.thanks": "Gràcies,",
|
||||
"emails.recovery.buttonText": "Restableix la contrasenya",
|
||||
"emails.recovery.thanks": "Gràcies",
|
||||
"emails.recovery.signature": "Equip {{project}}",
|
||||
"emails.invitation.subject": "Invitació a l'equip {{team}} a {{project}}",
|
||||
"emails.invitation.hello": "Hola,",
|
||||
"emails.invitation.subject": "Invitació a l'equip %s a s%",
|
||||
"emails.invitation.hello": "Hola",
|
||||
"emails.invitation.body": "Aquest correu se t'ha enviat perquè {{owner}} vol convidar-te a formar part de l'equip {{team}} al {{project}}.",
|
||||
"emails.invitation.footer": "Si no és del teu interès, pots ignorar aquest missatge.",
|
||||
"emails.invitation.thanks": "Gràcies,",
|
||||
"emails.invitation.buttonText": "Accepta la invitació a {{team}}",
|
||||
"emails.invitation.thanks": "Gràcies",
|
||||
"emails.invitation.signature": "Equip {{project}}",
|
||||
"locale.country.unknown": "Desconegut",
|
||||
"countries.af": "Afganistan",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Granada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guaiana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Hondures",
|
||||
"countries.hr": "Croàcia",
|
||||
"countries.ht": "Haití",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Nova Zelanda",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palestina",
|
||||
"countries.pa": "Panamà",
|
||||
"countries.pe": "Perú",
|
||||
"countries.ph": "Filipines",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Tunísia",
|
||||
"countries.tr": "Turquia",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwan",
|
||||
"countries.tz": "Tanzània",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ucraïna",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "Amèrica del Nord",
|
||||
"continents.oc": "Oceania",
|
||||
"continents.sa": "Amèrica del Sud",
|
||||
"emails.magicSession.optionButton": "Feu clic al botó de sota per iniciar sessió de manera segura al vostre compte {{project}}. Caducarà en 1 hora.",
|
||||
"emails.magicSession.buttonText": "Inicia sessió a {{project}}",
|
||||
"emails.magicSession.clientInfo": "Aquest inici de sessió s'ha sol·licitat utilitzant {{agentClient}} en {{agentDevice}} {{agentOs}}. Si no has sol·licitat l'inici de sessió, pots ignorar aquest correu electrònic amb seguretat.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "La frase de seguretat d'aquest correu electrònic és {{phrase}}. Podeu confiar en aquest correu si aquesta frase coincideix amb la frase mostrada durant l'inici de sessió.",
|
||||
"emails.magicSession.optionUrl": "Si no podeu iniciar sessió utilitzant el botó de dalt, visiteu l'enllaç següent:",
|
||||
"emails.otpSession.subject": "Inici de sessió de {{project}}",
|
||||
"emails.otpSession.hello": "Hola,",
|
||||
"emails.otpSession.description": "Introduïu el següent codi de verificació quan us ho sol·licitin per iniciar sessió de manera segura al vostre compte {{project}}. Caducarà en 15 minuts.",
|
||||
"emails.otpSession.clientInfo": "Aquest inici de sessió s'ha sol·licitat utilitzant {{agentClient}} en {{agentDevice}} {{agentOs}}. Si no has sol·licitat l'inici de sessió, pots ignorar aquest correu electrònic sense cap problema.",
|
||||
"emails.otpSession.securityPhrase": "La frase de seguretat d'aquest correu electrònic és {{phrase}}. Podeu confiar en aquest correu electrònic si aquesta frase coincideix amb la frase mostrada durant l'inici de sessió.",
|
||||
"emails.otpSession.thanks": "Gràcies,",
|
||||
"emails.otpSession.signature": "equip {{project}}"
|
||||
}
|
||||
"continents.sa": "Amèrica del Sud"
|
||||
}
|
||||
@@ -2,28 +2,30 @@
|
||||
"settings.inspire": "\"Umění moudrosti je umění vědět, co přehlédnout.\"",
|
||||
"settings.locale": "cs",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} tým",
|
||||
"emails.sender": "%s tým",
|
||||
"emails.verification.subject": "",
|
||||
"emails.verification.hello": ",",
|
||||
"emails.verification.hello": "",
|
||||
"emails.verification.body": "",
|
||||
"emails.verification.footer": "",
|
||||
"emails.verification.thanks": ",",
|
||||
"emails.verification.thanks": "",
|
||||
"emails.verification.signature": "",
|
||||
"emails.magicSession.subject": "",
|
||||
"emails.magicSession.hello": ",",
|
||||
"emails.magicSession.thanks": ",",
|
||||
"emails.magicSession.hello": "",
|
||||
"emails.magicSession.body": "",
|
||||
"emails.magicSession.footer": "",
|
||||
"emails.magicSession.thanks": "",
|
||||
"emails.magicSession.signature": "",
|
||||
"emails.recovery.subject": "",
|
||||
"emails.recovery.hello": ",",
|
||||
"emails.recovery.hello": "",
|
||||
"emails.recovery.body": "",
|
||||
"emails.recovery.footer": "",
|
||||
"emails.recovery.thanks": ",",
|
||||
"emails.recovery.thanks": "",
|
||||
"emails.recovery.signature": "",
|
||||
"emails.invitation.subject": "",
|
||||
"emails.invitation.hello": ",",
|
||||
"emails.invitation.hello": "",
|
||||
"emails.invitation.body": "",
|
||||
"emails.invitation.footer": "",
|
||||
"emails.invitation.thanks": ",",
|
||||
"emails.invitation.thanks": "",
|
||||
"emails.invitation.signature": "",
|
||||
"locale.country.unknown": "Neznámý",
|
||||
"countries.af": "Afghánistán",
|
||||
@@ -98,7 +100,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Chorvatsko",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -162,7 +163,6 @@
|
||||
"countries.nz": "Nový Zéland",
|
||||
"countries.om": "Omán",
|
||||
"countries.pk": "Pákistán",
|
||||
"countries.ps": "Palestina",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Filipíny",
|
||||
@@ -206,7 +206,6 @@
|
||||
"countries.tn": "Tunisko",
|
||||
"countries.tr": "Turecko",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Tchaj-wan",
|
||||
"countries.tz": "Tanzanie",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukraine",
|
||||
@@ -229,18 +228,5 @@
|
||||
"continents.eu": "Evropa",
|
||||
"continents.na": "Severní Amerika",
|
||||
"continents.oc": "Oceánie",
|
||||
"continents.sa": "Jižní Amerika",
|
||||
"emails.magicSession.optionButton": "Klikněte na tlačítko níže pro bezpečné přihlášení do vašeho účtu {{project}}. Platnost vyprší za 1 hodinu.",
|
||||
"emails.magicSession.buttonText": "Přihlaste se k {{project}}",
|
||||
"emails.magicSession.clientInfo": "Toto přihlášení bylo požadováno prostřednictvím {{agentClient}} na {{agentDevice}} {{agentOs}}. Pokud jste se nepřihlašovali, můžete tento e-mail bezpečně ignorovat.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Bezpečnostní fráze pro tento e-mail je {{phrase}}. Tomuto e-mailu můžete důvěřovat, pokud tato fráze odpovídá frázi zobrazené při přihlášení.",
|
||||
"emails.magicSession.optionUrl": "Pokud se nemůžete přihlásit pomocí výše uvedeného tlačítka, prosím navštivte následující odkaz:",
|
||||
"emails.otpSession.subject": "{{project}} Přihlášení",
|
||||
"emails.otpSession.hello": "Ahoj,",
|
||||
"emails.otpSession.description": "Zadejte následující ověřovací kód, když budete vyzváni, abyste se bezpečně přihlásili ke svému účtu {{project}}. Platnost kódu vyprší za 15 minut.",
|
||||
"emails.otpSession.clientInfo": "Tento přihlašovací pokus byl proveden pomocí {{agentClient}} na zařízení {{agentDevice}} {{agentOs}}. Pokud jste se nepřihlašovali, tento e-mail můžete bezpečně ignorovat.",
|
||||
"emails.otpSession.securityPhrase": "Bezpečnostní fráze pro tento e-mail je {{phrase}}. Tomuto e-mailu můžete důvěřovat, pokud se tato fráze shoduje s frází zobrazenou při přihlášení.",
|
||||
"emails.otpSession.thanks": "Děkuji,",
|
||||
"emails.otpSession.signature": "tým {{project}}"
|
||||
}
|
||||
"continents.sa": "Jižní Amerika"
|
||||
}
|
||||
@@ -1,32 +1,31 @@
|
||||
{
|
||||
"settings.inspire": "\"Kunsten at være klog er kunsten at vide, hvad man skal overse.\"",
|
||||
"settings.inspire": "\"Kunsten at være klog er kunsten at vide, hvad man skal overse.\"",
|
||||
"settings.locale": "da",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Team",
|
||||
"emails.sender": "%s Team",
|
||||
"emails.verification.subject": "Konto Verifikation",
|
||||
"emails.verification.hello": "Hej {{user}},",
|
||||
"emails.verification.hello": "Hej {{name}}",
|
||||
"emails.verification.body": "Følg dette link, for at verificere din email adresse.",
|
||||
"emails.verification.footer": "Hvis du ikke har bedt om at verificere denne adresse, ignorer venligst denne besked.",
|
||||
"emails.verification.thanks": "Tak,",
|
||||
"emails.verification.buttonText": "Bekræft e-mailadresse",
|
||||
"emails.verification.thanks": "Tak",
|
||||
"emails.verification.signature": "{{project}} team",
|
||||
"emails.magicSession.subject": "Login",
|
||||
"emails.magicSession.hello": "Hej,",
|
||||
"emails.magicSession.thanks": "Tak,",
|
||||
"emails.magicSession.body": "Følg dette link for at logge ind.",
|
||||
"emails.magicSession.footer": "Hvis du ikke har bedt om at logge ind med denne email, ignorer venligst denne besked.",
|
||||
"emails.magicSession.thanks": "Tak",
|
||||
"emails.magicSession.signature": "{{project}} team",
|
||||
"emails.recovery.subject": "Nulstil Password",
|
||||
"emails.recovery.hello": "Hej {{user}},",
|
||||
"emails.recovery.hello": "Hej {{name}}",
|
||||
"emails.recovery.body": "Følg dette link for at nulstille koden til {{project}}.",
|
||||
"emails.recovery.footer": "Hvis du ikke har bedt om at nulstille dit password, ignorer venligst denne besked.",
|
||||
"emails.recovery.thanks": "Tak,",
|
||||
"emails.recovery.buttonText": "Nulstil adgangskode",
|
||||
"emails.recovery.thanks": "Tak",
|
||||
"emails.recovery.signature": "{{project}} team",
|
||||
"emails.invitation.subject": "Invitation til {{team}} Team på {{project}}",
|
||||
"emails.invitation.hello": "Hej,",
|
||||
"emails.invitation.subject": "Invitation til %s Team på %s",
|
||||
"emails.invitation.hello": "Hej",
|
||||
"emails.invitation.body": "Denne mail blev sendt til dig, fordi {{owner}} vil invitere dig til at blive medlem af {{team}} teamet på {{project}}.",
|
||||
"emails.invitation.footer": "Hvis du ikke er interesseret, ignorer venligst denne besked.",
|
||||
"emails.invitation.thanks": "Tak,",
|
||||
"emails.invitation.buttonText": "Accepter invitation til {{team}}",
|
||||
"emails.invitation.thanks": "Tak",
|
||||
"emails.invitation.signature": "{{project}} team",
|
||||
"locale.country.unknown": "Ukendt",
|
||||
"countries.af": "Afghanistan",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Kroatien",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "New Zealand",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palæstina",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Filippinerne",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Tunisien",
|
||||
"countries.tr": "Tyrkiet",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwan",
|
||||
"countries.tz": "Tanzania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukraine",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "Nordamerica",
|
||||
"continents.oc": "Oceanien",
|
||||
"continents.sa": "Sydamerica",
|
||||
"emails.magicSession.optionButton": "Klik på knappen nedenfor for sikkert at logge ind på din {{project}} konto. Den udløber om 1 time.",
|
||||
"emails.magicSession.buttonText": "Log ind på {{project}}",
|
||||
"emails.magicSession.clientInfo": "Denne log ind blev anmodet ved hjælp af {{agentClient}} på {{agentDevice}} {{agentOs}}. Hvis du ikke anmodede om log ind, kan du trygt ignorere denne e-mail.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Sikkerhedsfrasen for denne e-mail er {{phrase}}. Du kan stole på denne e-mail, hvis denne frase matcher den viste frase under log ind.",
|
||||
"emails.magicSession.optionUrl": "Hvis du ikke kan logge ind ved at bruge knappen ovenfor, besøg venligst følgende link:",
|
||||
"emails.otpSession.subject": "{{project}} Login",
|
||||
"emails.otpSession.hello": "Hej,",
|
||||
"emails.otpSession.description": "Indtast følgende bekræftelseskode, når du bliver bedt om det, for sikkert at logge ind på din {{project}} konto. Den udløber om 15 minutter.",
|
||||
"emails.otpSession.clientInfo": "Denne indlogning blev anmodet om ved hjælp af {{agentClient}} på {{agentDevice}} {{agentOs}}. Hvis du ikke har anmodet om indlogningen, kan du trygt ignorere denne e-mail.",
|
||||
"emails.otpSession.securityPhrase": "Sikkerhedsfrasen for denne e-mail er {{phrase}}. Du kan stole på denne e-mail, hvis denne frase matcher frasen vist under login.",
|
||||
"emails.otpSession.thanks": "Tak,",
|
||||
"emails.otpSession.signature": "{{project}} team"
|
||||
"continents.sa": "Sydamerica"
|
||||
}
|
||||
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"Die Kunst, weise zu sein, ist die Kunst, zu wissen, was zu übersehen ist.\"",
|
||||
"settings.locale": "de",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Team",
|
||||
"emails.sender": "%s Team",
|
||||
"emails.verification.subject": "Kontoverifizierung",
|
||||
"emails.verification.hello": "Hey {{user}},",
|
||||
"emails.verification.hello": "Hey {{name}}",
|
||||
"emails.verification.body": "Folge diesem Link, um deine E-Mail-Adresse zu bestätigen.",
|
||||
"emails.verification.footer": "Solltest du keine Verifizierung dieser E-Mail-Adresse angefordert haben, kannst du diese Nachricht ignorieren.",
|
||||
"emails.verification.thanks": "Danke,",
|
||||
"emails.verification.buttonText": "E-Mail-Adresse bestätigen",
|
||||
"emails.verification.thanks": "Danke",
|
||||
"emails.verification.signature": "{{project}}-Team",
|
||||
"emails.magicSession.subject": "Login",
|
||||
"emails.magicSession.hello": "Hey,",
|
||||
"emails.magicSession.thanks": "Danke,",
|
||||
"emails.magicSession.body": "Folge diesem Link, um dich einzuloggen.",
|
||||
"emails.magicSession.footer": "Solltest du keinen Login für diese E-Mail-Adresse angefordert haben, kannst du diese Nachricht ignorieren.",
|
||||
"emails.magicSession.thanks": "Danke",
|
||||
"emails.magicSession.signature": "{{project}}-Team",
|
||||
"emails.recovery.subject": "Kennwort zurücksetzen",
|
||||
"emails.recovery.hello": "Hallo {{user}},",
|
||||
"emails.recovery.hello": "Hallo {{name}}",
|
||||
"emails.recovery.body": "Folge diesem Link, um dein {{project}}-Kennwort zurückzusetzen.",
|
||||
"emails.recovery.footer": "Solltest du keine Kennwort-Zurücksetzung angefordert haben, kannst du diese Nachricht ignorieren.",
|
||||
"emails.recovery.thanks": "Danke,",
|
||||
"emails.recovery.buttonText": "Passwort zurücksetzen",
|
||||
"emails.recovery.thanks": "Danke",
|
||||
"emails.recovery.signature": "{{project}}-Team",
|
||||
"emails.invitation.subject": "Einladung zum {{team}}-Team auf {{project}}",
|
||||
"emails.invitation.hello": "Hello,",
|
||||
"emails.invitation.subject": "Einladung zum %s-Team auf %s",
|
||||
"emails.invitation.hello": "Hello",
|
||||
"emails.invitation.body": "Du erhälst diese E-Mail, weil {{owner}} dich in das Team {{team}} auf {{project}} eingeladen hat.",
|
||||
"emails.invitation.footer": "Wenn du nicht interessiert bist, kannst du diese Nachricht ignorieren.",
|
||||
"emails.invitation.thanks": "Danke,",
|
||||
"emails.invitation.buttonText": "Einladung zu {{team}} annehmen",
|
||||
"emails.invitation.thanks": "Danke",
|
||||
"emails.invitation.signature": "{{project}}-Team",
|
||||
"locale.country.unknown": "Unbekannt",
|
||||
"countries.af": "Afghanistan",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Kroatien",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Neuseeland",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palästina",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Philippinen",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Tunesien",
|
||||
"countries.tr": "Türkei",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwan",
|
||||
"countries.tz": "Tansania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukraine",
|
||||
@@ -232,19 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "Nordamerika",
|
||||
"continents.oc": "Ozeanien",
|
||||
"continents.sa": "Südamerika",
|
||||
"emails.magicSession.optionButton": "Klicken Sie auf den unten stehenden Button, um sicher in Ihr {{project}}-Konto einzuloggen. Er verfällt in 1 Stunde.",
|
||||
"emails.magicSession.buttonText": "Melden Sie sich bei {{project}} an",
|
||||
"emails.magicSession.clientInfo": "Dieser Anmeldeversuch wurde über {{agentClient}} auf {{agentDevice}} {{agentOs}} angefordert. Wenn Sie die Anmeldung nicht angefordert haben, können Sie diese E-Mail getrost ignorieren.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Die Sicherheitsphrase für diese E-Mail lautet {{phrase}}. Sie können dieser E-Mail vertrauen, wenn diese Phrase mit der Phrase übereinstimmt, die beim Anmelden angezeigt wurde.",
|
||||
"emails.magicSession.optionUrl": "Wenn Sie sich nicht über den obigen Button anmelden können, besuchen Sie bitte den folgenden Link:",
|
||||
"emails.otpSession.subject": "{{project}} Anmeldung",
|
||||
"emails.otpSession.hello": "Hallo,",
|
||||
"emails.otpSession.description": "Geben Sie den folgenden Verifizierungscode ein, wenn Sie aufgefordert werden, um sich sicher in Ihrem {{project}} Konto anzumelden. Er verfällt in 15 Minuten.",
|
||||
"emails.otpSession.clientInfo": "Diese Anmeldung wurde über {{agentClient}} auf {{agentDevice}} {{agentOs}} angefordert. Wenn Sie die Anmeldung nicht angefordert haben, können Sie diese E-Mail getrost ignorieren.",
|
||||
"emails.otpSession.securityPhrase": "Die Sicherheitsphrase für diese E-Mail lautet {{phrase}}. Sie können dieser E-Mail vertrauen, wenn diese Phrase mit der Phrase übereinstimmt, die beim Anmelden angezeigt wird.",
|
||||
"emails.otpSession.thanks": "Danke,",
|
||||
"emails.otpSession.signature": "{{project}} Team",
|
||||
"mock": "Eine Beispielübersetzung für Testzwecke."
|
||||
"continents.sa": "Südamerika"
|
||||
}
|
||||
|
||||
@@ -2,31 +2,30 @@
|
||||
"settings.inspire": "\"Η τέχνη του να είσαι σοφός, είναι η τέχνη να ξέρεις τι πρέπει να παραβλέψεις.\"",
|
||||
"settings.locale": "gr",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "Ομάδα {{project}}",
|
||||
"emails.sender": "Ομάδα %s",
|
||||
"emails.verification.subject": "Επαλήθευση Λογαριασμού",
|
||||
"emails.verification.hello": "Γεια σου {{user}},",
|
||||
"emails.verification.hello": "Γεια σου {{name}}",
|
||||
"emails.verification.body": "Ακολουθήστε αυτό το link για να επαληθεύσετε τη δ/νση του email σας",
|
||||
"emails.verification.footer": "Εάν δεν ζητήσατε επαλήθευση αυτής της δ/νσης email, μπορείτε να αγνοήσετε αυτό το μήνυμα",
|
||||
"emails.verification.thanks": "Ευχαριστούμε,",
|
||||
"emails.verification.buttonText": "Επιβεβαιώστε διεύθυνση email",
|
||||
"emails.verification.thanks": "Ευχαριστούμε",
|
||||
"emails.verification.signature": "Η ομάδα του {{project}}",
|
||||
"emails.magicSession.subject": "Είσοδος",
|
||||
"emails.magicSession.hello": "Γεια σου,",
|
||||
"emails.magicSession.thanks": "Ευχαριστούμε,",
|
||||
"emails.magicSession.body": "Ακολουθήστε αυτό το link για να συνδεθείτε",
|
||||
"emails.magicSession.footer": "Εάν δεν ζητήσατε να συνδεθείτε χρησιμοποιώντας αυτό το email, μπορείτε να αγνοήσετε αυτό το μήνυμα.",
|
||||
"emails.magicSession.thanks": "Ευχαριστούμε",
|
||||
"emails.magicSession.signature": "Η ομάδα του {{project}}",
|
||||
"emails.recovery.subject": "Αλλαγή κωδικού πρόσβασης",
|
||||
"emails.recovery.hello": "Γεια σου {{user}},",
|
||||
"emails.recovery.hello": "Γεια σου {{name}}",
|
||||
"emails.recovery.body": "Ακολουθήστε αυτό το link για να αλλάξετε τον {{project}} κωδικό σας",
|
||||
"emails.recovery.footer": "Εάν δεν ζητήσατε αλλαγή του κωδικού σας πρόσβασης, μπορείτε να αγνοήσετε αυτό το μήνυμα",
|
||||
"emails.recovery.thanks": "Ευχαριστούμε,",
|
||||
"emails.recovery.buttonText": "Επαναφορά κωδικού πρόσβασης",
|
||||
"emails.recovery.thanks": "Ευχαριστούμε",
|
||||
"emails.recovery.signature": "Η ομάδα του {{project}}",
|
||||
"emails.invitation.subject": "Πρόσκληση στην {{team}} Ομάδα στον {{project}}",
|
||||
"emails.invitation.hello": "Γεια σου,",
|
||||
"emails.invitation.subject": "Πρόσκληση στην %s Ομάδα στον %s",
|
||||
"emails.invitation.hello": "Γεια σου",
|
||||
"emails.invitation.body": "Αυτό το email στάλθηκε επειδή ο/η {{owner}} θέλει να σας προσκαλέσει να γίνετε μέλος της ομάδας {{team}} του {{project}}.",
|
||||
"emails.invitation.footer": "Εάν δεν ενδιαφέρεστε, μπορείτε να αγνοήσετε αυτό το μήνυμα.",
|
||||
"emails.invitation.thanks": "Ευχαριστούμε,",
|
||||
"emails.invitation.buttonText": "Αποδεχόμενος την πρόσκληση στην {{team}}",
|
||||
"emails.invitation.thanks": "Ευχαριστούμε",
|
||||
"emails.invitation.signature": "Η ομάδα του {{project}}",
|
||||
"locale.country.unknown": "Άγνωστο",
|
||||
"countries.af": "Αφγανιστάν",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Γρενάδα",
|
||||
"countries.gt": "Γουατεμάλα",
|
||||
"countries.gy": "Γουιάνα",
|
||||
"countries.hk": "Χονγκ Κονγκ",
|
||||
"countries.hn": "Ονδούρα",
|
||||
"countries.hr": "Κροατία",
|
||||
"countries.ht": "Αϊτή",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Νέα Ζηλανδία",
|
||||
"countries.om": "Ομάν",
|
||||
"countries.pk": "Πακιστάν",
|
||||
"countries.ps": "Παλαιστίνη",
|
||||
"countries.pa": "Παναμάς",
|
||||
"countries.pe": "Περού",
|
||||
"countries.ph": "Φιλιππίνες",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Τυνησία",
|
||||
"countries.tr": "Τουρκία",
|
||||
"countries.tv": "Τουβαλού",
|
||||
"countries.tw": "Ταϊβάν",
|
||||
"countries.tz": "Τανζανία",
|
||||
"countries.ug": "Ουγκάντα",
|
||||
"countries.ua": "Ουκρανία",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "Ευρώπη",
|
||||
"continents.na": "Βόρεια Αμερική",
|
||||
"continents.oc": "Ωκεανία",
|
||||
"continents.sa": "Νότια Αμερική",
|
||||
"emails.magicSession.optionButton": "Κάντε κλικ στο κουμπί παρακάτω για να συνδεθείτε με ασφάλεια στον λογαριασμό σας στο {{project}}. Θα λήξει σε 1 ώρα.",
|
||||
"emails.magicSession.buttonText": "Συνδεθείτε στο {{project}}",
|
||||
"emails.magicSession.clientInfo": "Η σύνδεση αυτή ζητήθηκε χρησιμοποιώντας το {{agentClient}} στο {{agentDevice}} {{agentOs}}. Εάν δεν ζητήσατε τη σύνδεση, μπορείτε να αγνοήσετε με ασφάλεια αυτό το email.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "Η φράση ασφαλείας για αυτό το email είναι {{phrase}}. Μπορείτε να εμπιστευτείτε αυτό το email αν αυτή η φράση ταιριάζει με τη φράση που εμφανίζεται κατά την είσοδο.",
|
||||
"emails.magicSession.optionUrl": "Εάν δεν μπορείτε να συνδεθείτε χρησιμοποιώντας το παραπάνω κουμπί, παρακαλώ επισκεφτείτε τον παρακάτω σύνδεσμο:",
|
||||
"emails.otpSession.subject": "{{project}} Σύνδεση",
|
||||
"emails.otpSession.hello": "Γεια σου,",
|
||||
"emails.otpSession.description": "Εισάγετε τον ακόλουθο κωδικό επαλήθευσης όταν σας ζητηθεί για να συνδεθείτε με ασφάλεια στον λογαριασμό σας {{project}}. Θα λήξει σε 15 λεπτά.",
|
||||
"emails.otpSession.clientInfo": "Αυτή η είσοδος ζητήθηκε με χρήση {{agentClient}} σε {{agentDevice}} {{agentOs}}. Εάν δεν ζητήσατε την είσοδο, μπορείτε να αγνοήσετε αυτό το email με ασφάλεια.",
|
||||
"emails.otpSession.securityPhrase": "Η φράση ασφαλείας για αυτό το email είναι {{phrase}}. Μπορείτε να εμπιστευτείτε αυτό το email αν αυτή η φράση ταιριάζει με τη φράση που εμφανίστηκε κατά την είσοδο.",
|
||||
"emails.otpSession.thanks": "Ευχαριστώ,",
|
||||
"emails.otpSession.signature": "ομάδα {{project}}"
|
||||
"continents.sa": "Νότια Αμερική"
|
||||
}
|
||||
|
||||
@@ -2,92 +2,37 @@
|
||||
"settings.inspire": "\"The art of being wise is the art of knowing what to overlook.\"",
|
||||
"settings.locale": "en",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "{{project}} Team",
|
||||
"emails.verification.subject": "Account Verification for {{project}}",
|
||||
"emails.verification.preview": "Verify your email to activate your {{project}} account.",
|
||||
"emails.verification.heading": "Verify your email to start using {{project}}",
|
||||
"emails.verification.hello": "Hello {{user}},",
|
||||
"emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.",
|
||||
"emails.sender": "%s Team",
|
||||
"emails.verification.subject": "Account Verification",
|
||||
"emails.verification.hello": "Hey {{name}}",
|
||||
"emails.verification.body": "Follow this link to verify your email address.",
|
||||
"emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.",
|
||||
"emails.verification.thanks": "Thanks,",
|
||||
"emails.verification.buttonText": "Confirm email address",
|
||||
"emails.verification.thanks": "Thanks",
|
||||
"emails.verification.signature": "{{project}} team",
|
||||
"emails.magicSession.subject": "{{project}} Login",
|
||||
"emails.magicSession.preview": "Sign in to {{project}} with your secure link. Expires in 1 hour.",
|
||||
"emails.magicSession.hello": "Hello {{user}},",
|
||||
"emails.magicSession.optionButton": "Click the button below to securely sign in to your {{b}}{{project}}{{/b}} account. This link will expire in 1 hour.",
|
||||
"emails.magicSession.buttonText": "Sign in to {{project}}",
|
||||
"emails.magicSession.optionUrl": "If you are unable to sign in using the button above, please visit the following link:",
|
||||
"emails.magicSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
|
||||
"emails.magicSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.",
|
||||
"emails.magicSession.thanks": "Thanks,",
|
||||
"emails.magicSession.subject": "Login",
|
||||
"emails.magicSession.hello": "Hey,",
|
||||
"emails.magicSession.body": "Follow this link to login.",
|
||||
"emails.magicSession.footer": "If you didn’t ask to login using this email, you can ignore this message.",
|
||||
"emails.magicSession.thanks": "Thanks",
|
||||
"emails.magicSession.signature": "{{project}} team",
|
||||
"emails.sessionAlert.subject": "Security alert: new session on your {{project}} account",
|
||||
"emails.sessionAlert.preview": "New login detected on {{project}} at {{time}} UTC.",
|
||||
"emails.sessionAlert.hello": "Hello {{user}},",
|
||||
"emails.sessionAlert.body": "A new session has been created on your {{b}}{{project}}{{/b}} account, {{b}}on {{date}}, {{year}} at {{time}} UTC{{/b}}.\nHere are the details of the new session: ",
|
||||
"emails.sessionAlert.listDevice": "Device: {{b}}{{device}}{{/b}}",
|
||||
"emails.sessionAlert.listIpAddress": "IP Address: {{b}}{{ipAddress}}{{/b}}",
|
||||
"emails.sessionAlert.listCountry": "Country: {{b}}{{country}}{{/b}}",
|
||||
"emails.sessionAlert.footer": "If this was you, there's nothing more you need to do.\nIf you didn't initiate this session or suspect any unauthorized activity, please secure your account.",
|
||||
"emails.sessionAlert.thanks": "Thanks,",
|
||||
"emails.sessionAlert.signature": "{{project}} team",
|
||||
"emails.otpSession.subject": "OTP for {{project}} Login",
|
||||
"emails.otpSession.preview": "Use OTP {{otp}} to sign in to {{project}}. Expires in 15 minutes.",
|
||||
"emails.otpSession.heading": "Login with OTP to use {{project}}",
|
||||
"emails.otpSession.hello": "Hello {{user}},",
|
||||
"emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.",
|
||||
"emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
|
||||
"emails.otpSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.",
|
||||
"emails.otpSession.thanks": "Thanks,",
|
||||
"emails.otpSession.signature": "{{project}} team",
|
||||
"emails.mfaChallenge.subject": "Verification Code for {{project}}",
|
||||
"emails.mfaChallenge.preview": "Use code {{otp}} for two-step verification in {{project}}. Expires in 15 minutes.",
|
||||
"emails.mfaChallenge.heading": "Complete two-step verification to use {{project}}",
|
||||
"emails.mfaChallenge.hello": "Hello {{user}},",
|
||||
"emails.mfaChallenge.description": "Enter the following code to confirm your two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.",
|
||||
"emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.",
|
||||
"emails.mfaChallenge.thanks": "Thanks,",
|
||||
"emails.mfaChallenge.signature": "{{project}} team",
|
||||
"emails.recovery.subject": "Password Reset for {{project}}",
|
||||
"emails.recovery.preview": "Reset your {{project}} password using the link.",
|
||||
"emails.recovery.hello": "Hello {{user}},",
|
||||
"emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.",
|
||||
"emails.recovery.footer": "If you didn't ask to reset your password, you can ignore this message.",
|
||||
"emails.recovery.thanks": "Thanks,",
|
||||
"emails.recovery.buttonText": "Reset password",
|
||||
"emails.recovery.subject": "Password Reset",
|
||||
"emails.recovery.hello": "Hello {{name}}",
|
||||
"emails.recovery.body": "Follow this link to reset your {{project}} password.",
|
||||
"emails.recovery.footer": "If you didn’t ask to reset your password, you can ignore this message.",
|
||||
"emails.recovery.thanks": "Thanks",
|
||||
"emails.recovery.signature": "{{project}} team",
|
||||
"emails.csvExport.success.subject": "Your CSV export is ready",
|
||||
"emails.csvExport.success.preview": "Your data export has been completed successfully.",
|
||||
"emails.csvExport.success.hello": "Hello {{user}},",
|
||||
"emails.csvExport.success.body": "Your CSV export is ready to download. Click the button below to download your data export.",
|
||||
"emails.csvExport.success.footer": "This download link will expire in 1 hour.",
|
||||
"emails.csvExport.success.thanks": "Thanks,",
|
||||
"emails.csvExport.success.buttonText": "Download CSV",
|
||||
"emails.csvExport.success.signature": "Appwrite team",
|
||||
"emails.csvExport.failure.subject": "Your CSV export failed - file too large",
|
||||
"emails.csvExport.failure.preview": "Your data export failed because the file size exceeds your plan limit.",
|
||||
"emails.csvExport.failure.hello": "Hello {{user}},",
|
||||
"emails.csvExport.failure.body": "Your CSV export could not be completed because the export file size ({{size}}MB) exceeds your plan limit. Please consider upgrading your plan or exporting a smaller dataset.",
|
||||
"emails.csvExport.failure.footer": "If you have any questions, please contact our support team.",
|
||||
"emails.csvExport.failure.thanks": "Thanks,",
|
||||
"emails.csvExport.failure.signature": "{{project}} team",
|
||||
"emails.invitation.subject": "Invitation to {{team}} Team at {{project}}",
|
||||
"emails.invitation.preview": "{{owner}} invited you to join {{team}} at {{project}}",
|
||||
"emails.invitation.hello": "Hello {{user}},",
|
||||
"emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} invited you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.",
|
||||
"emails.invitation.subject": "Invitation to %s Team at %s",
|
||||
"emails.invitation.hello": "Hello",
|
||||
"emails.invitation.body": "This mail was sent to you because {{owner}} wanted to invite you to become a member of the {{team}} team at {{project}}.",
|
||||
"emails.invitation.footer": "If you are not interested, you can ignore this message.",
|
||||
"emails.invitation.thanks": "Thanks,",
|
||||
"emails.invitation.buttonText": "Accept invite to {{team}}",
|
||||
"emails.invitation.thanks": "Thanks",
|
||||
"emails.invitation.signature": "{{project}} team",
|
||||
"emails.certificate.subject": "Certificate failure for {{domain}}",
|
||||
"emails.certificate.preview": "Your domain {{domain}} certificate generation has failed.",
|
||||
"emails.certificate.hello": "Hello,",
|
||||
"emails.certificate.subject": "Certificate failure for %s",
|
||||
"emails.certificate.hello": "Hello",
|
||||
"emails.certificate.body": "Certificate for your domain '{{domain}}' could not be generated. This is attempt no. {{attempt}}, and the failure was caused by: {{error}}",
|
||||
"emails.certificate.footer": "Your previous certificate will be valid for 30 days since the first failure. We highly recommend investigating this case, otherwise your domain will end up without a valid SSL communication.",
|
||||
"emails.certificate.thanks": "Thanks,",
|
||||
"emails.certificate.thanks": "Thanks",
|
||||
"emails.certificate.signature": "{{project}} team",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"locale.country.unknown": "Unknown",
|
||||
"countries.af": "Afghanistan",
|
||||
"countries.ao": "Angola",
|
||||
@@ -161,7 +106,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Croatia",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -225,7 +169,6 @@
|
||||
"countries.nz": "New Zealand",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palestine",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Philippines",
|
||||
@@ -269,7 +212,6 @@
|
||||
"countries.tn": "Tunisia",
|
||||
"countries.tr": "Turkey",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwan",
|
||||
"countries.tz": "Tanzania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukraine",
|
||||
@@ -292,6 +234,5 @@
|
||||
"continents.eu": "Europe",
|
||||
"continents.na": "North America",
|
||||
"continents.oc": "Oceania",
|
||||
"continents.sa": "South America",
|
||||
"mock": "A mock translation for testing purposes."
|
||||
"continents.sa": "South America"
|
||||
}
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
{
|
||||
"settings.locale": "eo",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "Teamo {{project}}",
|
||||
"emails.verification.subject": "Konta Konfirmo",
|
||||
"emails.verification.hello": "Saluton {{user}},",
|
||||
"emails.verification.body": "Alklaku ĉi tiun ligon por kontroli vian retpoŝtan adreson.",
|
||||
"emails.verification.footer": "Se vi ne petis ĉi tiun konfirmon de ĉi tiu retpoŝto, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.verification.thanks": "Dankegon.,",
|
||||
"emails.verification.buttonText": "Konfirmi retadreson",
|
||||
"emails.verification.signature": "Teamo {{project}}",
|
||||
"emails.magicSession.subject": "Login",
|
||||
"emails.magicSession.hello": "Saluton,",
|
||||
"emails.magicSession.thanks": "Dankegon,",
|
||||
"emails.magicSession.signature": "Teamo {{project}}",
|
||||
"emails.recovery.subject": "Parsvorta Restarigo",
|
||||
"emails.recovery.hello": "Saluton {{user}},",
|
||||
"emails.recovery.body": "Alklaku ĉi tiun ligon por reagordi vian pasvorton. {{project}}",
|
||||
"emails.recovery.footer": "Se vi ne petis reagordi vian pasvorton, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.recovery.thanks": "Dankegon,",
|
||||
"emails.recovery.buttonText": "Pasvorton restarigi",
|
||||
"emails.recovery.signature": "Teamo {{project}}",
|
||||
"emails.invitation.subject": "Invito al la Teamo {{team}} em {{project}}",
|
||||
"emails.invitation.hello": "Dankegon,",
|
||||
"emails.invitation.body": "Ĉi tiu retpoŝto estis sendita ĉar la {{owner}} volas inviti vin fariĝi membro de la Teamo {{team}} en {{project}}.",
|
||||
"emails.invitation.footer": "Se vi ne interesiĝas, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.invitation.thanks": "Dankegon,",
|
||||
"emails.invitation.buttonText": "Akcepti inviton al {{team}}",
|
||||
"emails.invitation.signature": "Teamo {{project}}",
|
||||
"locale.country.unknown": "Unknown",
|
||||
{
|
||||
"settings.locale": "eo",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "Teamo %s",
|
||||
"emails.verification.subject": "Konta Konfirmo",
|
||||
"emails.verification.hello": "Saluton {{name}}",
|
||||
"emails.verification.body": "Alklaku ĉi tiun ligon por kontroli vian retpoŝtan adreson.",
|
||||
"emails.verification.footer": "Se vi ne petis ĉi tiun konfirmon de ĉi tiu retpoŝto, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.verification.thanks": "Dankegon.",
|
||||
"emails.verification.signature": "Teamo {{project}}",
|
||||
"emails.magicSession.subject": "Login",
|
||||
"emails.magicSession.hello": "Saluton,",
|
||||
"emails.magicSession.body": "Alklaku ĉi tiun ligon por eniri.",
|
||||
"emails.magicSession.footer": "Se vi ne petis ĉi tiun konfirmon de ĉi tiu retpoŝto, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.magicSession.thanks": "Dankegon",
|
||||
"emails.magicSession.signature": "Teamo {{project}}",
|
||||
"emails.recovery.subject": "Parsvorta Restarigo",
|
||||
"emails.recovery.hello": "Saluton {{name}}",
|
||||
"emails.recovery.body": "Alklaku ĉi tiun ligon por reagordi vian pasvorton. {{project}}",
|
||||
"emails.recovery.footer": "Se vi ne petis reagordi vian pasvorton, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.recovery.thanks": "Dankegon",
|
||||
"emails.recovery.signature": "Teamo {{project}}",
|
||||
"emails.invitation.subject": "Invito al la Teamo %s em %s",
|
||||
"emails.invitation.hello": "Dankegon",
|
||||
"emails.invitation.body": "Ĉi tiu retpoŝto estis sendita ĉar la {{owner}} volas inviti vin fariĝi membro de la Teamo {{team}} en {{project}}.",
|
||||
"emails.invitation.footer": "Se vi ne interesiĝas, vi povas ignori ĉi tiun mesaĝon.",
|
||||
"emails.invitation.thanks": "Dankegon",
|
||||
"emails.invitation.signature": "Teamo {{project}}",
|
||||
"locale.country.unknown": "Unknown",
|
||||
"countries.af": "Afghanistan",
|
||||
"countries.ao": "Angola",
|
||||
"countries.al": "Albania",
|
||||
@@ -100,7 +99,6 @@
|
||||
"countries.gd": "Grenada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guyana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Croatia",
|
||||
"countries.ht": "Haiti",
|
||||
@@ -164,7 +162,6 @@
|
||||
"countries.nz": "New Zealand",
|
||||
"countries.om": "Oman",
|
||||
"countries.pk": "Pakistan",
|
||||
"countries.ps": "Palestinio",
|
||||
"countries.pa": "Panama",
|
||||
"countries.pe": "Peru",
|
||||
"countries.ph": "Philippines",
|
||||
@@ -208,7 +205,6 @@
|
||||
"countries.tn": "Tunisia",
|
||||
"countries.tr": "Turkey",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Tajvano",
|
||||
"countries.tz": "Tanzania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ukraine",
|
||||
@@ -231,19 +227,5 @@
|
||||
"continents.eu": "Europe",
|
||||
"continents.na": "North America",
|
||||
"continents.oc": "Oceania",
|
||||
"continents.sa": "South America",
|
||||
"settings.inspire": "\"La arto esti saĝa estas la arto scii kion preteratenti.\"",
|
||||
"emails.magicSession.optionButton": "Alklaku la suban butonon por sekure ensaluti al via {{project}}-konto. Ĝi eksvalidiĝos post 1 horo.",
|
||||
"emails.magicSession.buttonText": "Ensalutu al {{project}}",
|
||||
"emails.magicSession.clientInfo": "Ĉi tiu ensaluto estis petita per {{agentClient}} en {{agentDevice}} {{agentOs}}. Se vi ne petis la ensaluton, vi povas sekure ignori ĉi tiun retpoŝton.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "La sekureca frazo por ĉi tiu retpoŝto estas {{phrase}}. Vi povas fidi ĉi tiun retpoŝton se ĉi tiu frazo kongruas kun la frazo montrita dum ensaluto.",
|
||||
"emails.magicSession.optionUrl": "Se vi ne povas ensaluti per la supra butono, bonvolu viziti la jenan ligilon:",
|
||||
"emails.otpSession.subject": "{{project}} Ensaluto",
|
||||
"emails.otpSession.hello": "Saluton,",
|
||||
"emails.otpSession.description": "Enigu la jenan kontrolkodon kiam oni petos ĝin por sekure ensaluti en vian {{project}} konton. Ĝi eksvalidiĝos post 15 minutoj.",
|
||||
"emails.otpSession.clientInfo": "Ĉi tiu ensaluto estis petita per {{agentClient}} en {{agentDevice}} {{agentOs}}. Se vi ne petis la ensaluton, vi povas sekure ignori ĉi tiun retpoŝton.",
|
||||
"emails.otpSession.securityPhrase": "Sekureca frazo por ĉi tiu retpoŝto estas {{phrase}}. Vi povas fidi ĉi tiun retpoŝton se tiu ĉi frazo kongruas kun la frazo montrita dum ensaluto.",
|
||||
"emails.otpSession.thanks": "Dankon,",
|
||||
"emails.otpSession.signature": "teamo de {{project}}"
|
||||
"continents.sa": "South America"
|
||||
}
|
||||
|
||||
@@ -2,32 +2,31 @@
|
||||
"settings.inspire": "\"El arte de ser sabio es el arte de saber qué pasar por alto\"",
|
||||
"settings.locale": "es",
|
||||
"settings.direction": "ltr",
|
||||
"emails.sender": "El equipo de {{project}}",
|
||||
"emails.sender": "Equipo %s",
|
||||
"emails.verification.subject": "Verificación de cuenta",
|
||||
"emails.verification.hello": "Hola, {{name}}.,",
|
||||
"emails.verification.body": "Haz clic en este enlace para verificar tu correo:",
|
||||
"emails.verification.hello": "Hola {{name}}",
|
||||
"emails.verification.body": "Haz clic en este enlace para verificar tu correo.",
|
||||
"emails.verification.footer": "Si no has solicitado verificar este correo, puedes ignorar este mensaje.",
|
||||
"emails.verification.thanks": "Gracias.,",
|
||||
"emails.verification.buttonText": "Confirmar dirección de correo",
|
||||
"emails.verification.signature": "El equipo de {{project}}.",
|
||||
"emails.verification.thanks": "Gracias",
|
||||
"emails.verification.signature": "Equipo de {{project}}",
|
||||
"emails.magicSession.subject": "Inicio de sesión",
|
||||
"emails.magicSession.hello": "Hola,",
|
||||
"emails.magicSession.thanks": "Gracias.,",
|
||||
"emails.magicSession.signature": "El equipo de {{project}}",
|
||||
"emails.magicSession.body": "Haz clic en este enlace para iniciar sesión.",
|
||||
"emails.magicSession.footer": "Si no has solicitado ingresar usando este correo, puedes ignorar este mensaje.",
|
||||
"emails.magicSession.thanks": "Gracias",
|
||||
"emails.magicSession.signature": "Equipo de {{project}}",
|
||||
"emails.recovery.subject": "Restablecer contraseña",
|
||||
"emails.recovery.hello": "Hola, {{name}}.,",
|
||||
"emails.recovery.body": "Haz clic en este enlace para restablecer la contraseña de {{project}}:",
|
||||
"emails.recovery.hello": "Hola {{name}}",
|
||||
"emails.recovery.body": "Haz clic en este enlace para restablecer la contraseña de {{project}}.",
|
||||
"emails.recovery.footer": "Si no has solicitado restablecer la contraseña, puedes ignorar este mensaje.",
|
||||
"emails.recovery.thanks": "Gracias.,",
|
||||
"emails.recovery.buttonText": "Restablecer contraseña",
|
||||
"emails.recovery.signature": "El equipo de {{project}}",
|
||||
"emails.invitation.subject": "Invitación al equipo {{team}} en {{project}}",
|
||||
"emails.invitation.hello": "Hola,",
|
||||
"emails.invitation.body": "Este correo ha sido enviado a petición de {{owner}} quién quiere invitarte a formar parte del equipo {{team}} en {{project}}.",
|
||||
"emails.invitation.footer": "Si no estás interesado, puedes ignorar este mensaje.",
|
||||
"emails.invitation.thanks": "Gracias.,",
|
||||
"emails.invitation.buttonText": "Aceptar invitación a {{team}}",
|
||||
"emails.invitation.signature": "El equipo de {{project}}",
|
||||
"emails.recovery.thanks": "Gracias",
|
||||
"emails.recovery.signature": "Equipo de {{project}}",
|
||||
"emails.invitation.subject": "Invitación al equipo %s en %s",
|
||||
"emails.invitation.hello": "Hola",
|
||||
"emails.invitation.body": "Este correo ha sido enviado a petición de {{owner}} quien quiere invitarte a formar parte del equipo {{team}} en {{project}}.",
|
||||
"emails.invitation.footer": "Si no estas interesado, puedes ignorar este mensaje.",
|
||||
"emails.invitation.thanks": "Gracias",
|
||||
"emails.invitation.signature": "Equipo de {{project}}",
|
||||
"locale.country.unknown": "Desconocido",
|
||||
"countries.af": "Afganistán",
|
||||
"countries.ao": "Angola",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "Granada",
|
||||
"countries.gt": "Guatemala",
|
||||
"countries.gy": "Guayana",
|
||||
"countries.hk": "Hong Kong",
|
||||
"countries.hn": "Honduras",
|
||||
"countries.hr": "Croacia",
|
||||
"countries.ht": "Haití",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "Nueva Zelanda",
|
||||
"countries.om": "Omán",
|
||||
"countries.pk": "Pakistán",
|
||||
"countries.ps": "Palestina",
|
||||
"countries.pa": "Panamá",
|
||||
"countries.pe": "Perú",
|
||||
"countries.ph": "Filipinas",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "Túnez",
|
||||
"countries.tr": "Turquía",
|
||||
"countries.tv": "Tuvalu",
|
||||
"countries.tw": "Taiwán",
|
||||
"countries.tz": "Tanzania",
|
||||
"countries.ug": "Uganda",
|
||||
"countries.ua": "Ucrania",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "Europa",
|
||||
"continents.na": "América del Norte",
|
||||
"continents.oc": "Oceanía",
|
||||
"continents.sa": "América del Sur",
|
||||
"emails.magicSession.optionButton": "Haz clic en el botón de abajo para iniciar sesión de forma segura en tu cuenta de {{project}}. Caducará en 1 hora.",
|
||||
"emails.magicSession.buttonText": "Iniciar sesión en {{project}}",
|
||||
"emails.magicSession.clientInfo": "Este inicio de sesión fue solicitado usando {{agentClient}} en {{agentDevice}} {{agentOs}}. Si no solicitaste el inicio de sesión, puedes ignorar este correo electrónico de forma segura.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "La frase de seguridad para este correo electrónico es {{phrase}}. Puedes confiar en este correo electrónico si esta frase coincide con la frase que se muestra durante el inicio de sesión.",
|
||||
"emails.magicSession.optionUrl": "Si no puedes iniciar sesión utilizando el botón anterior, visita el siguiente enlace:",
|
||||
"emails.otpSession.subject": "Inicio de sesión en {{project}}",
|
||||
"emails.otpSession.hello": "Hola,",
|
||||
"emails.otpSession.description": "Ingrese el siguiente código de verificación cuando se le solicite para iniciar sesión de forma segura en su cuenta de {{project}}. Expirará en 15 minutos.",
|
||||
"emails.otpSession.clientInfo": "Este inicio de sesión fue solicitado usando {{agentClient}} en {{agentDevice}} {{agentOs}}. Si no solicitaste el inicio de sesión, puedes ignorar este correo electrónico de forma segura.",
|
||||
"emails.otpSession.securityPhrase": "La frase de seguridad para este correo electrónico es {{phrase}}. Puedes confiar en este correo si esta frase coincide con la frase mostrada durante el inicio de sesión.",
|
||||
"emails.otpSession.thanks": "Gracias.,",
|
||||
"emails.otpSession.signature": "El equipo de {{project}}"
|
||||
}
|
||||
"continents.sa": "América del Sur"
|
||||
}
|
||||
@@ -2,32 +2,31 @@
|
||||
"settings.inspire": "\"هنر خردمند بودن این است که بدانید چه چیزی را نادیده بگیرید.\"",
|
||||
"settings.locale": "fa",
|
||||
"settings.direction": "rtl",
|
||||
"emails.sender": "تیم {{project}}",
|
||||
"emails.sender": "تیم %s",
|
||||
"emails.verification.subject": "تأیید حساب",
|
||||
"emails.verification.hello": "سلام {{user}}،",
|
||||
"emails.verification.hello": "سلام {{name}}",
|
||||
"emails.verification.body": "برای تأیید ایمیلتان پیوند زیر را دنبال کنید.",
|
||||
"emails.verification.footer": "اگر شما درخواست تأیید حساب ندادهاید، میتوانید این پیام را نادیده بگیرید.",
|
||||
"emails.verification.thanks": "سپاس فراوان،",
|
||||
"emails.verification.buttonText": "آدرس ایمیل را تایید کنید",
|
||||
"emails.verification.signature": "تیم {{user}}",
|
||||
"emails.verification.thanks": "سپاس فراوان",
|
||||
"emails.verification.signature": "تیم {{name}}",
|
||||
"emails.magicSession.subject": "ورود به حساب کاربری",
|
||||
"emails.magicSession.hello": "سلام،",
|
||||
"emails.magicSession.thanks": "سپاس فراوان،",
|
||||
"emails.magicSession.signature": "تیم {{user}}",
|
||||
"emails.magicSession.body": "برای ورود به حسابتان پیوند زیر را دنبال کنید.",
|
||||
"emails.magicSession.footer": "اگر شما درخواست ورود به حساب کاربری با استفاده از این ایمیل را ندادهاید، میتوانید این پیام را نادیده بگیرید.",
|
||||
"emails.magicSession.thanks": "سپاس فراوان",
|
||||
"emails.magicSession.signature": "تیم {{name}}",
|
||||
"emails.recovery.subject": "بازیابی گذرواژه",
|
||||
"emails.recovery.hello": "سلام {{user}}،",
|
||||
"emails.recovery.hello": "سلام {{name}}",
|
||||
"emails.recovery.body": "برای بازیابی گذرواژهتان پیوند زیر را دنبال کنید.",
|
||||
"emails.recovery.footer": "اگر شما درخواست بازیابی گذرواژه ندادهاید، میتوانید این پیام را نادیده بگیرید.",
|
||||
"emails.recovery.thanks": "سپاس فراوان،",
|
||||
"emails.recovery.buttonText": "بازنشانی رمز عبور",
|
||||
"emails.recovery.signature": "تیم {{user}}",
|
||||
"emails.invitation.subject": "دعوت به تیم {{team}} در {{project}}",
|
||||
"emails.invitation.hello": "سلام،",
|
||||
"emails.recovery.thanks": "سپاس فراوان",
|
||||
"emails.recovery.signature": "تیم {{name}}",
|
||||
"emails.invitation.subject": "دعوت به تیم %s در %s",
|
||||
"emails.invitation.hello": "سلام",
|
||||
"emails.invitation.body": "این ایمیل برای شما فرستاده شدهاست زیرا {{owner}} میخواهد شما را به تیم {{team}} در پروژهی {{project}} بیفزاید.",
|
||||
"emails.invitation.footer": "اگر علاقه ندارید، میتوانید این پیام را نادیده بگیرید.",
|
||||
"emails.invitation.thanks": "سپاس فراوان،",
|
||||
"emails.invitation.buttonText": "دعوت را به {{team}} بپذیرید",
|
||||
"emails.invitation.signature": "تیم {{user}}",
|
||||
"emails.invitation.thanks": "سپاس فراوان",
|
||||
"emails.invitation.signature": "تیم {{name}}",
|
||||
"locale.country.unknown": "ناشناخته",
|
||||
"countries.af": "افغانستان",
|
||||
"countries.ao": "آنگولا",
|
||||
@@ -101,7 +100,6 @@
|
||||
"countries.gd": "گرنادا",
|
||||
"countries.gt": "گواتمالا",
|
||||
"countries.gy": "گویان",
|
||||
"countries.hk": "هنگ کنگ",
|
||||
"countries.hn": "هندوراس",
|
||||
"countries.hr": "کرواسی",
|
||||
"countries.ht": "هائیتی",
|
||||
@@ -165,7 +163,6 @@
|
||||
"countries.nz": "نیوزلند",
|
||||
"countries.om": "عمان",
|
||||
"countries.pk": "پاکستان",
|
||||
"countries.ps": "فلسطین",
|
||||
"countries.pa": "پاناما",
|
||||
"countries.pe": "پرو",
|
||||
"countries.ph": "فیلیپین",
|
||||
@@ -209,7 +206,6 @@
|
||||
"countries.tn": "تونس",
|
||||
"countries.tr": "ترکیه",
|
||||
"countries.tv": "تووالو",
|
||||
"countries.tw": "تایوان",
|
||||
"countries.tz": "تانزانیا",
|
||||
"countries.ug": "اوگاندا",
|
||||
"countries.ua": "اوکراین",
|
||||
@@ -232,18 +228,5 @@
|
||||
"continents.eu": "اروپا",
|
||||
"continents.na": "آمریکای شمالی",
|
||||
"continents.oc": "اقیانوسیه",
|
||||
"continents.sa": "آمریکای جنوبی",
|
||||
"emails.magicSession.optionButton": "بر روی دکمه زیر کلیک کنید تا به صورت امن وارد حساب {{project}} خود شوید. این دکمه یک ساعت دیگر منقضی میشود.",
|
||||
"emails.magicSession.buttonText": "ورود به {{project}}",
|
||||
"emails.magicSession.clientInfo": "این ورود به سیستم با استفاده از {{agentClient}} در {{agentDevice}} {{agentOs}} درخواست شده است. اگر شما این ورود به سیستم را درخواست نکردهاید، میتوانید به راحتی این ایمیل را نادیده بگیرید.",
|
||||
"sms.verification.body": "{{secret}}",
|
||||
"emails.magicSession.securityPhrase": "عبارت امنیتی برای این ایمیل {{phrase}} است. اگر این عبارت با عبارت نشان داده شده در هنگام ورود به سیستم مطابقت داشت، میتوانید به این ایمیل اعتماد کنید.",
|
||||
"emails.magicSession.optionUrl": "اگر قادر به ورود با استفاده از دکمه بالا نیستید، لطفاً از لینک زیر دیدن فرمایید:",
|
||||
"emails.otpSession.subject": "ورود {{project}}",
|
||||
"emails.otpSession.hello": "سلام،",
|
||||
"emails.otpSession.description": "وقتی از شما خواسته شد، کد تأیید زیر را برای ورود ایمن به حساب کاربری {{project}} خود وارد کنید. این کد تا ۱۵ دقیقه دیگر منقضی میشود.",
|
||||
"emails.otpSession.clientInfo": "این ورود به سیستم با استفاده از {{agentClient}} در {{agentDevice}} {{agentOs}} درخواست شده است. اگر شما این ورود به سیستم را درخواست نکردهاید، میتوانید به راحتی این ایمیل را نادیده بگیرید.",
|
||||
"emails.otpSession.securityPhrase": "عبارت امنیتی برای این ایمیل {{phrase}} است. اگر این عبارت با عبارت نشان داده شده هنگام ورود به سیستم مطابقت داشته باشد، میتوانید به این ایمیل اعتماد کنید.",
|
||||
"emails.otpSession.thanks": "متشکرم،",
|
||||
"emails.otpSession.signature": "تیم {{project}}"
|
||||
"continents.sa": "آمریکای جنوبی"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user