mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:21:09 +02:00
fix(uload): update Docker config and add env examples to apps/web
- Update Dockerfile for new apps/web structure - Fix docker-compose.coolify.yml to use correct Dockerfile - Add .env.example files to apps/web directory - Remove local build artifacts (.svelte-kit, build) - Update paraglide/i18n configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c712a2504a
commit
559eb08d8c
19 changed files with 605 additions and 172 deletions
136
pnpm-lock.yaml
generated
136
pnpm-lock.yaml
generated
|
|
@ -2299,6 +2299,9 @@ importers:
|
||||||
stripe:
|
stripe:
|
||||||
specifier: ^18.4.0
|
specifier: ^18.4.0
|
||||||
version: 18.5.0(@types/node@24.10.1)
|
version: 18.5.0(@types/node@24.10.1)
|
||||||
|
svelte-i18n:
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1(svelte@5.43.14)
|
||||||
svelte-sonner:
|
svelte-sonner:
|
||||||
specifier: ^1.0.5
|
specifier: ^1.0.5
|
||||||
version: 1.0.6(svelte@5.43.14)
|
version: 1.0.6(svelte@5.43.14)
|
||||||
|
|
@ -2306,9 +2309,6 @@ importers:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.20.0
|
specifier: ^9.20.0
|
||||||
version: 9.39.1
|
version: 9.39.1
|
||||||
'@inlang/paraglide-js':
|
|
||||||
specifier: ^2.2.0
|
|
||||||
version: 2.5.0
|
|
||||||
'@playwright/test':
|
'@playwright/test':
|
||||||
specifier: ^1.51.0
|
specifier: ^1.51.0
|
||||||
version: 1.56.1
|
version: 1.56.1
|
||||||
|
|
@ -4629,17 +4629,6 @@ packages:
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@inlang/paraglide-js@2.5.0':
|
|
||||||
resolution: {integrity: sha512-FnycOM6j0GYd/n97NCDyXJiHnyPYGPgufL640eZWs+rTIRrOgDVz/o77iWRYFZK84REOcmSDi0N6PbbY8NT8+A==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
'@inlang/recommend-sherlock@0.2.1':
|
|
||||||
resolution: {integrity: sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==}
|
|
||||||
|
|
||||||
'@inlang/sdk@2.4.9':
|
|
||||||
resolution: {integrity: sha512-cvz/C1rF5WBxzHbEoiBoI6Sz6q6M+TdxfWkEGBYTD77opY8i8WN01prUWXEM87GPF4SZcyIySez9U0Ccm12oFQ==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@inquirer/ansi@1.0.2':
|
'@inquirer/ansi@1.0.2':
|
||||||
resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==}
|
resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -4991,13 +4980,6 @@ packages:
|
||||||
'@js-sdsl/ordered-map@4.4.2':
|
'@js-sdsl/ordered-map@4.4.2':
|
||||||
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
|
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
|
||||||
|
|
||||||
'@lix-js/sdk@0.4.7':
|
|
||||||
resolution: {integrity: sha512-pRbW+joG12L0ULfMiWYosIW0plmW4AsUdiPCp+Z8rAsElJ+wJ6in58zhD3UwUcd4BNcpldEGjg6PdA7e0RgsDQ==}
|
|
||||||
engines: {node: '>=18'}
|
|
||||||
|
|
||||||
'@lix-js/server-protocol-schema@0.1.1':
|
|
||||||
resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==}
|
|
||||||
|
|
||||||
'@ljharb/through@2.3.14':
|
'@ljharb/through@2.3.14':
|
||||||
resolution: {integrity: sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==}
|
resolution: {integrity: sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -6114,9 +6096,6 @@ packages:
|
||||||
'@sinclair/typebox@0.27.8':
|
'@sinclair/typebox@0.27.8':
|
||||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
||||||
|
|
||||||
'@sinclair/typebox@0.31.28':
|
|
||||||
resolution: {integrity: sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==}
|
|
||||||
|
|
||||||
'@sinclair/typebox@0.34.41':
|
'@sinclair/typebox@0.34.41':
|
||||||
resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
|
resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
|
||||||
|
|
||||||
|
|
@ -6345,10 +6324,6 @@ packages:
|
||||||
resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==}
|
resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@sqlite.org/sqlite-wasm@3.48.0-build4':
|
|
||||||
resolution: {integrity: sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
'@stablelib/base64@1.0.1':
|
'@stablelib/base64@1.0.1':
|
||||||
resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
|
resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
|
||||||
|
|
||||||
|
|
@ -8299,10 +8274,6 @@ packages:
|
||||||
consola@2.15.3:
|
consola@2.15.3:
|
||||||
resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
|
resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
|
||||||
|
|
||||||
consola@3.4.0:
|
|
||||||
resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
|
|
||||||
engines: {node: ^14.18.0 || >=16.10.0}
|
|
||||||
|
|
||||||
consola@3.4.2:
|
consola@3.4.2:
|
||||||
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
|
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
|
||||||
engines: {node: ^14.18.0 || >=16.10.0}
|
engines: {node: ^14.18.0 || >=16.10.0}
|
||||||
|
|
@ -8539,14 +8510,6 @@ packages:
|
||||||
resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
|
resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
dedent@1.5.1:
|
|
||||||
resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==}
|
|
||||||
peerDependencies:
|
|
||||||
babel-plugin-macros: ^3.1.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
babel-plugin-macros:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
dedent@1.7.0:
|
dedent@1.7.0:
|
||||||
resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==}
|
resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -10638,10 +10601,6 @@ packages:
|
||||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
human-id@4.1.2:
|
|
||||||
resolution: {integrity: sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
human-signals@2.1.0:
|
human-signals@2.1.0:
|
||||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||||
engines: {node: '>=10.17.0'}
|
engines: {node: '>=10.17.0'}
|
||||||
|
|
@ -11347,9 +11306,6 @@ packages:
|
||||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
js-sha256@0.11.1:
|
|
||||||
resolution: {integrity: sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==}
|
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
|
|
@ -14191,11 +14147,6 @@ packages:
|
||||||
sprintf-js@1.0.3:
|
sprintf-js@1.0.3:
|
||||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
|
|
||||||
sqlite-wasm-kysely@0.3.0:
|
|
||||||
resolution: {integrity: sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg==}
|
|
||||||
peerDependencies:
|
|
||||||
kysely: '*'
|
|
||||||
|
|
||||||
stable-hash@0.0.5:
|
stable-hash@0.0.5:
|
||||||
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
||||||
|
|
||||||
|
|
@ -15144,10 +15095,6 @@ packages:
|
||||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
unplugin@2.3.11:
|
|
||||||
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
|
|
||||||
engines: {node: '>=18.12.0'}
|
|
||||||
|
|
||||||
unrs-resolver@1.11.1:
|
unrs-resolver@1.11.1:
|
||||||
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
|
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
|
||||||
|
|
||||||
|
|
@ -15225,9 +15172,6 @@ packages:
|
||||||
url-parse@1.5.10:
|
url-parse@1.5.10:
|
||||||
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
||||||
|
|
||||||
urlpattern-polyfill@10.1.0:
|
|
||||||
resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==}
|
|
||||||
|
|
||||||
use-callback-ref@1.3.3:
|
use-callback-ref@1.3.3:
|
||||||
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
|
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -15641,9 +15585,6 @@ packages:
|
||||||
resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==}
|
resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
webpack-virtual-modules@0.6.2:
|
|
||||||
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
|
||||||
|
|
||||||
webpack@5.100.2:
|
webpack@5.100.2:
|
||||||
resolution: {integrity: sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==}
|
resolution: {integrity: sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
@ -19085,32 +19026,6 @@ snapshots:
|
||||||
'@img/sharp-win32-x64@0.34.5':
|
'@img/sharp-win32-x64@0.34.5':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@inlang/paraglide-js@2.5.0':
|
|
||||||
dependencies:
|
|
||||||
'@inlang/recommend-sherlock': 0.2.1
|
|
||||||
'@inlang/sdk': 2.4.9
|
|
||||||
commander: 11.1.0
|
|
||||||
consola: 3.4.0
|
|
||||||
json5: 2.2.3
|
|
||||||
unplugin: 2.3.11
|
|
||||||
urlpattern-polyfill: 10.1.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- babel-plugin-macros
|
|
||||||
|
|
||||||
'@inlang/recommend-sherlock@0.2.1':
|
|
||||||
dependencies:
|
|
||||||
comment-json: 4.4.1
|
|
||||||
|
|
||||||
'@inlang/sdk@2.4.9':
|
|
||||||
dependencies:
|
|
||||||
'@lix-js/sdk': 0.4.7
|
|
||||||
'@sinclair/typebox': 0.31.28
|
|
||||||
kysely: 0.27.6
|
|
||||||
sqlite-wasm-kysely: 0.3.0(kysely@0.27.6)
|
|
||||||
uuid: 10.0.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- babel-plugin-macros
|
|
||||||
|
|
||||||
'@inquirer/ansi@1.0.2': {}
|
'@inquirer/ansi@1.0.2': {}
|
||||||
|
|
||||||
'@inquirer/checkbox@4.3.2(@types/node@22.19.1)':
|
'@inquirer/checkbox@4.3.2(@types/node@22.19.1)':
|
||||||
|
|
@ -19660,20 +19575,6 @@ snapshots:
|
||||||
|
|
||||||
'@js-sdsl/ordered-map@4.4.2': {}
|
'@js-sdsl/ordered-map@4.4.2': {}
|
||||||
|
|
||||||
'@lix-js/sdk@0.4.7':
|
|
||||||
dependencies:
|
|
||||||
'@lix-js/server-protocol-schema': 0.1.1
|
|
||||||
dedent: 1.5.1
|
|
||||||
human-id: 4.1.2
|
|
||||||
js-sha256: 0.11.1
|
|
||||||
kysely: 0.27.6
|
|
||||||
sqlite-wasm-kysely: 0.3.0(kysely@0.27.6)
|
|
||||||
uuid: 10.0.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- babel-plugin-macros
|
|
||||||
|
|
||||||
'@lix-js/server-protocol-schema@0.1.1': {}
|
|
||||||
|
|
||||||
'@ljharb/through@2.3.14':
|
'@ljharb/through@2.3.14':
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
|
|
@ -20986,8 +20887,6 @@ snapshots:
|
||||||
|
|
||||||
'@sinclair/typebox@0.27.8': {}
|
'@sinclair/typebox@0.27.8': {}
|
||||||
|
|
||||||
'@sinclair/typebox@0.31.28': {}
|
|
||||||
|
|
||||||
'@sinclair/typebox@0.34.41': {}
|
'@sinclair/typebox@0.34.41': {}
|
||||||
|
|
||||||
'@sinonjs/commons@3.0.1':
|
'@sinonjs/commons@3.0.1':
|
||||||
|
|
@ -21340,8 +21239,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@sqlite.org/sqlite-wasm@3.48.0-build4': {}
|
|
||||||
|
|
||||||
'@stablelib/base64@1.0.1': {}
|
'@stablelib/base64@1.0.1': {}
|
||||||
|
|
||||||
'@standard-schema/spec@1.0.0': {}
|
'@standard-schema/spec@1.0.0': {}
|
||||||
|
|
@ -24347,8 +24244,6 @@ snapshots:
|
||||||
|
|
||||||
consola@2.15.3: {}
|
consola@2.15.3: {}
|
||||||
|
|
||||||
consola@3.4.0: {}
|
|
||||||
|
|
||||||
consola@3.4.2: {}
|
consola@3.4.2: {}
|
||||||
|
|
||||||
content-disposition@0.5.4:
|
content-disposition@0.5.4:
|
||||||
|
|
@ -24590,8 +24485,6 @@ snapshots:
|
||||||
|
|
||||||
decode-uri-component@0.2.2: {}
|
decode-uri-component@0.2.2: {}
|
||||||
|
|
||||||
dedent@1.5.1: {}
|
|
||||||
|
|
||||||
dedent@1.7.0: {}
|
dedent@1.7.0: {}
|
||||||
|
|
||||||
deep-eql@5.0.2: {}
|
deep-eql@5.0.2: {}
|
||||||
|
|
@ -27969,8 +27862,6 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
human-id@4.1.2: {}
|
|
||||||
|
|
||||||
human-signals@2.1.0: {}
|
human-signals@2.1.0: {}
|
||||||
|
|
||||||
husky@9.1.7: {}
|
husky@9.1.7: {}
|
||||||
|
|
@ -29157,8 +29048,6 @@ snapshots:
|
||||||
|
|
||||||
joycon@3.1.1: {}
|
joycon@3.1.1: {}
|
||||||
|
|
||||||
js-sha256@0.11.1: {}
|
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-tokens@9.0.1: {}
|
js-tokens@9.0.1: {}
|
||||||
|
|
@ -29371,7 +29260,8 @@ snapshots:
|
||||||
|
|
||||||
konva@10.0.12: {}
|
konva@10.0.12: {}
|
||||||
|
|
||||||
kysely@0.27.6: {}
|
kysely@0.27.6:
|
||||||
|
optional: true
|
||||||
|
|
||||||
lan-network@0.1.7: {}
|
lan-network@0.1.7: {}
|
||||||
|
|
||||||
|
|
@ -33047,11 +32937,6 @@ snapshots:
|
||||||
|
|
||||||
sprintf-js@1.0.3: {}
|
sprintf-js@1.0.3: {}
|
||||||
|
|
||||||
sqlite-wasm-kysely@0.3.0(kysely@0.27.6):
|
|
||||||
dependencies:
|
|
||||||
'@sqlite.org/sqlite-wasm': 3.48.0-build4
|
|
||||||
kysely: 0.27.6
|
|
||||||
|
|
||||||
stable-hash@0.0.5: {}
|
stable-hash@0.0.5: {}
|
||||||
|
|
||||||
stack-generator@2.0.10:
|
stack-generator@2.0.10:
|
||||||
|
|
@ -34183,13 +34068,6 @@ snapshots:
|
||||||
|
|
||||||
unpipe@1.0.0: {}
|
unpipe@1.0.0: {}
|
||||||
|
|
||||||
unplugin@2.3.11:
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/remapping': 2.3.5
|
|
||||||
acorn: 8.15.0
|
|
||||||
picomatch: 4.0.3
|
|
||||||
webpack-virtual-modules: 0.6.2
|
|
||||||
|
|
||||||
unrs-resolver@1.11.1:
|
unrs-resolver@1.11.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
napi-postinstall: 0.3.4
|
napi-postinstall: 0.3.4
|
||||||
|
|
@ -34242,8 +34120,6 @@ snapshots:
|
||||||
querystringify: 2.2.0
|
querystringify: 2.2.0
|
||||||
requires-port: 1.0.0
|
requires-port: 1.0.0
|
||||||
|
|
||||||
urlpattern-polyfill@10.1.0: {}
|
|
||||||
|
|
||||||
use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.1.0):
|
use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
|
|
@ -34772,8 +34648,6 @@ snapshots:
|
||||||
|
|
||||||
webpack-sources@3.3.3: {}
|
webpack-sources@3.3.3: {}
|
||||||
|
|
||||||
webpack-virtual-modules@0.6.2: {}
|
|
||||||
|
|
||||||
webpack@5.100.2:
|
webpack@5.100.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint-scope': 3.7.7
|
'@types/eslint-scope': 3.7.7
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,25 @@ FROM node:20-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Dependencies installieren
|
# Copy package files from apps/web
|
||||||
COPY package*.json ./
|
COPY apps/web/package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
RUN npm ci --legacy-peer-deps
|
RUN npm ci --legacy-peer-deps
|
||||||
|
|
||||||
# App bauen
|
# Copy web app source
|
||||||
COPY . .
|
COPY apps/web/ .
|
||||||
|
|
||||||
# Generate .svelte-kit directory first by running vite in prepare mode
|
# Generate .svelte-kit directory first by running vite in prepare mode
|
||||||
RUN npx vite build --mode prepare || true
|
RUN npx vite build --mode prepare || true
|
||||||
|
|
||||||
# Sync SvelteKit files
|
# Sync SvelteKit files
|
||||||
RUN npx svelte-kit sync
|
RUN npx svelte-kit sync
|
||||||
|
|
||||||
# Compile paraglide messages before build (using the correct output directory)
|
# Compile paraglide messages before build
|
||||||
RUN npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/paraglide
|
RUN npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/paraglide
|
||||||
|
|
||||||
# Now build the app
|
# Build the app
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Production Stage
|
# Production Stage
|
||||||
|
|
@ -26,7 +29,7 @@ FROM node:20-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Nur Node.js App
|
# Copy built app and dependencies
|
||||||
COPY --from=builder /app/build build/
|
COPY --from=builder /app/build build/
|
||||||
COPY --from=builder /app/package*.json ./
|
COPY --from=builder /app/package*.json ./
|
||||||
COPY --from=builder /app/node_modules node_modules/
|
COPY --from=builder /app/node_modules node_modules/
|
||||||
|
|
@ -42,5 +45,5 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Direkt Node starten (kein Supervisor nötig)
|
# Start Node server
|
||||||
CMD ["node", "build"]
|
CMD ["node", "build"]
|
||||||
|
|
|
||||||
36
uload/apps/web/.env.example
Normal file
36
uload/apps/web/.env.example
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# SvelteKit Configuration
|
||||||
|
PORT=3000
|
||||||
|
ORIGIN=https://your-domain.com
|
||||||
|
NODE_ENV=production
|
||||||
|
PUBLIC_APP_URL=https://ulo.ad
|
||||||
|
|
||||||
|
# Database (PostgreSQL)
|
||||||
|
# Development: Use local Docker container
|
||||||
|
DATABASE_URL=postgresql://uload:uload_dev_password_123@localhost:5432/uload_dev
|
||||||
|
# Production: Use your Coolify/Hetzner PostgreSQL container
|
||||||
|
# DATABASE_URL=postgresql://uload:your_password@uload-db-prod:5432/uload_prod
|
||||||
|
|
||||||
|
# File Storage (Cloudflare R2)
|
||||||
|
R2_ACCOUNT_ID=your_cloudflare_account_id
|
||||||
|
R2_ACCESS_KEY_ID=your_r2_access_key
|
||||||
|
R2_SECRET_ACCESS_KEY=your_r2_secret_key
|
||||||
|
R2_BUCKET_AVATARS=uload-avatars
|
||||||
|
R2_BUCKET_QR=uload-qr-codes
|
||||||
|
R2_PUBLIC_URL=https://files.ulo.ad
|
||||||
|
|
||||||
|
# Email (Resend)
|
||||||
|
RESEND_API_KEY=re_your_resend_api_key
|
||||||
|
RESEND_FROM_EMAIL=noreply@ulo.ad
|
||||||
|
|
||||||
|
# Umami Analytics (optional)
|
||||||
|
PUBLIC_UMAMI_URL=https://your-umami-instance.com
|
||||||
|
PUBLIC_UMAMI_WEBSITE_ID=your-website-id
|
||||||
|
|
||||||
|
# External Auth (to be implemented)
|
||||||
|
# AUTH_PROVIDER_CLIENT_ID=
|
||||||
|
# AUTH_PROVIDER_CLIENT_SECRET=
|
||||||
|
|
||||||
|
# Coolify specific (if needed)
|
||||||
|
# These will be set automatically by Coolify
|
||||||
|
# COOLIFY_URL=
|
||||||
|
# COOLIFY_TOKEN=
|
||||||
20
uload/apps/web/.env.production.example
Normal file
20
uload/apps/web/.env.production.example
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# SvelteKit Configuration
|
||||||
|
NODE_ENV=production
|
||||||
|
PORT=3000
|
||||||
|
ORIGIN=https://your-domain.com
|
||||||
|
PUBLIC_POCKETBASE_URL=https://your-domain.com/api
|
||||||
|
|
||||||
|
# PocketBase Admin Credentials
|
||||||
|
# These will be used to create the admin on first startup
|
||||||
|
POCKETBASE_ADMIN_EMAIL=till.schneider@memoro.ai
|
||||||
|
POCKETBASE_ADMIN_PASSWORD=p0ck3tRA1N
|
||||||
|
|
||||||
|
# Umami Analytics
|
||||||
|
# Replace with your actual Umami instance and website ID
|
||||||
|
PUBLIC_UMAMI_URL=https://your-umami-instance.com
|
||||||
|
PUBLIC_UMAMI_WEBSITE_ID=your-website-id
|
||||||
|
|
||||||
|
# Optional: Additional Configuration
|
||||||
|
# BODY_SIZE_LIMIT=512kb
|
||||||
|
# PROTOCOL_HEADER=x-forwarded-proto
|
||||||
|
# HOST_HEADER=x-forwarded-host
|
||||||
17
uload/apps/web/.env.stripe.example
Normal file
17
uload/apps/web/.env.stripe.example
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Stripe Configuration
|
||||||
|
# Copy this to .env.local or add to your .env file
|
||||||
|
|
||||||
|
# Stripe API Keys (get from https://dashboard.stripe.com/test/apikeys)
|
||||||
|
PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_PUBLISHABLE_KEY_HERE
|
||||||
|
STRIPE_SECRET_KEY=sk_test_YOUR_SECRET_KEY_HERE
|
||||||
|
|
||||||
|
# Stripe Product & Price IDs (will be created automatically by Claude)
|
||||||
|
STRIPE_PRODUCT_PRO=prod_xxx
|
||||||
|
STRIPE_PRICE_MONTHLY=price_xxx
|
||||||
|
STRIPE_PRICE_YEARLY=price_xxx
|
||||||
|
|
||||||
|
# Stripe Webhook Secret (from webhook endpoint in dashboard)
|
||||||
|
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
||||||
|
|
||||||
|
# App URL for redirects
|
||||||
|
PUBLIC_APP_URL=http://localhost:5173 # Production: https://ulo.ad
|
||||||
|
|
@ -3,10 +3,9 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm run paraglide:compile && vite dev",
|
"dev": "vite dev",
|
||||||
"build": "pnpm run paraglide:compile && vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"paraglide:compile": "paraglide-js compile --project ./project.inlang --outdir ./src/paraglide",
|
|
||||||
"test": "pnpm run test:unit && pnpm run test:e2e",
|
"test": "pnpm run test:unit && pnpm run test:e2e",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
|
|
@ -22,7 +21,6 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.20.0",
|
"@eslint/js": "^9.20.0",
|
||||||
"@inlang/paraglide-js": "^2.2.0",
|
|
||||||
"@playwright/test": "^1.51.0",
|
"@playwright/test": "^1.51.0",
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.0.0",
|
"@sveltejs/adapter-node": "^5.0.0",
|
||||||
|
|
@ -70,6 +68,7 @@
|
||||||
"postgres": "^3.4.7",
|
"postgres": "^3.4.7",
|
||||||
"resend": "^6.5.1",
|
"resend": "^6.5.1",
|
||||||
"stripe": "^18.4.0",
|
"stripe": "^18.4.0",
|
||||||
|
"svelte-i18n": "^4.0.1",
|
||||||
"svelte-sonner": "^1.0.5"
|
"svelte-sonner": "^1.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
uload/apps/web/project.inlang/.gitignore
vendored
Normal file
1
uload/apps/web/project.inlang/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
cache
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://inlang.com/schema/project-settings",
|
"$schema": "https://inlang.com/schema/project-settings",
|
||||||
"baseLocale": "en",
|
"sourceLanguageTag": "en",
|
||||||
"locales": ["en", "de", "es", "fr", "it"],
|
"languageTags": ["en", "de", "es", "fr", "it"],
|
||||||
"modules": [
|
"modules": [
|
||||||
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js",
|
"https://cdn.jsdelivr.net/npm/@inlang/plugin-json@4/dist/index.js",
|
||||||
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js"
|
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@latest/dist/index.js"
|
||||||
],
|
],
|
||||||
"plugin.inlang.json": {
|
"plugin.inlang.json": {
|
||||||
"pathPattern": "./messages/{locale}.json"
|
"pathPattern": "./messages/{languageTag}.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
60
uload/apps/web/src/lib/i18n/index.ts
Normal file
60
uload/apps/web/src/lib/i18n/index.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
import { init, register, locale, waitLocale } from 'svelte-i18n';
|
||||||
|
|
||||||
|
// Register all available locales
|
||||||
|
register('de', () => import('./locales/de.json'));
|
||||||
|
register('en', () => import('./locales/en.json'));
|
||||||
|
register('it', () => import('./locales/it.json'));
|
||||||
|
register('fr', () => import('./locales/fr.json'));
|
||||||
|
register('es', () => import('./locales/es.json'));
|
||||||
|
|
||||||
|
// List of supported locales
|
||||||
|
export const supportedLocales = ['de', 'en', 'it', 'fr', 'es'] as const;
|
||||||
|
export type SupportedLocale = (typeof supportedLocales)[number];
|
||||||
|
|
||||||
|
// Default locale
|
||||||
|
const defaultLocale = 'en';
|
||||||
|
|
||||||
|
// Get initial locale from browser or localStorage
|
||||||
|
function getInitialLocale(): SupportedLocale {
|
||||||
|
if (browser) {
|
||||||
|
// Check localStorage first
|
||||||
|
const stored = localStorage.getItem('locale');
|
||||||
|
if (stored && supportedLocales.includes(stored as SupportedLocale)) {
|
||||||
|
return stored as SupportedLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to browser language
|
||||||
|
const browserLang = navigator.language.split('-')[0];
|
||||||
|
if (supportedLocales.includes(browserLang as SupportedLocale)) {
|
||||||
|
return browserLang as SupportedLocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize i18n at module scope (required for SSR)
|
||||||
|
init({
|
||||||
|
fallbackLocale: defaultLocale,
|
||||||
|
initialLocale: getInitialLocale()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Also export initI18n for backwards compatibility
|
||||||
|
export function initI18n() {
|
||||||
|
init({
|
||||||
|
fallbackLocale: defaultLocale,
|
||||||
|
initialLocale: getInitialLocale()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set locale and persist to localStorage
|
||||||
|
export function setLocale(newLocale: SupportedLocale) {
|
||||||
|
locale.set(newLocale);
|
||||||
|
if (browser) {
|
||||||
|
localStorage.setItem('locale', newLocale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for locale to be loaded (useful for SSR)
|
||||||
|
export { waitLocale };
|
||||||
28
uload/apps/web/src/lib/i18n/locales/de.json
Normal file
28
uload/apps/web/src/lib/i18n/locales/de.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"nav_login": "Anmelden",
|
||||||
|
"nav_register": "Registrieren",
|
||||||
|
"nav_dashboard": "Dashboard",
|
||||||
|
"nav_folders": "Ordner",
|
||||||
|
"nav_profile": "Profil",
|
||||||
|
"nav_logout": "Abmelden",
|
||||||
|
"home_title": "Links intelligenter teilen",
|
||||||
|
"home_subtitle": "Erstelle verkürzte Links mit QR-Codes, benutzerdefinierten Namen und Analysen",
|
||||||
|
"home_url_label_qr": "URL zum Kodieren",
|
||||||
|
"home_url_label": "URL zum Kürzen",
|
||||||
|
"home_title_label": "Titel",
|
||||||
|
"home_title_placeholder": "Gib deinem Link einen Namen",
|
||||||
|
"home_description_label": "Beschreibung",
|
||||||
|
"home_description_placeholder": "Füge eine Beschreibung hinzu (optional)",
|
||||||
|
"home_expires_label": "Ablauf",
|
||||||
|
"home_expires_placeholder": "z.B. 7 Tage, 1 Monat",
|
||||||
|
"home_max_clicks_label": "Max. Klicks",
|
||||||
|
"home_max_clicks_placeholder": "Anzahl der Klicks begrenzen",
|
||||||
|
"home_password_label": "Passwort",
|
||||||
|
"home_password_placeholder": "Mit Passwort schützen",
|
||||||
|
"home_guest_info": "Du verwendest uload als Gast",
|
||||||
|
"auth_modal_signin": "Anmelden",
|
||||||
|
"home_guest_signin_hint": "um auf erweiterte Funktionen zuzugreifen",
|
||||||
|
"home_processing": "Verarbeitung...",
|
||||||
|
"home_submit_button_qr": "QR-Code generieren",
|
||||||
|
"home_submit_button": "Link erstellen"
|
||||||
|
}
|
||||||
144
uload/apps/web/src/lib/i18n/locales/en.json
Normal file
144
uload/apps/web/src/lib/i18n/locales/en.json
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
{
|
||||||
|
"nav_login": "Login",
|
||||||
|
"nav_register": "Register",
|
||||||
|
"nav_dashboard": "Dashboard",
|
||||||
|
"nav_folders": "Folders",
|
||||||
|
"nav_profile": "Profile",
|
||||||
|
"nav_logout": "Logout",
|
||||||
|
"nav_pricing": "Pricing",
|
||||||
|
|
||||||
|
"home_title": "Share Links Smarter",
|
||||||
|
"home_subtitle": "Create shortened links with QR codes, custom names, and analytics",
|
||||||
|
"home_url_label_qr": "URL to encode",
|
||||||
|
"home_url_label": "URL to shorten",
|
||||||
|
"home_title_label": "Title",
|
||||||
|
"home_title_placeholder": "Give your link a name",
|
||||||
|
"home_description_label": "Description",
|
||||||
|
"home_description_placeholder": "Add a description (optional)",
|
||||||
|
"home_expires_label": "Expiration",
|
||||||
|
"home_expires_placeholder": "e.g., 7 days, 1 month",
|
||||||
|
"home_max_clicks_label": "Max clicks",
|
||||||
|
"home_max_clicks_placeholder": "Limit number of clicks",
|
||||||
|
"home_password_label": "Password",
|
||||||
|
"home_password_placeholder": "Protect with password",
|
||||||
|
"home_guest_info": "You're using uload as a guest",
|
||||||
|
"home_guest_signin_hint": "to access advanced features",
|
||||||
|
"home_processing": "Processing...",
|
||||||
|
"home_submit_button_qr": "Generate QR Code",
|
||||||
|
"home_submit_button": "Create Link",
|
||||||
|
|
||||||
|
"auth_modal_signin": "Sign in",
|
||||||
|
"auth_sign_in": "Sign In",
|
||||||
|
"auth_login_button": "Login",
|
||||||
|
"auth_login_button_loading": "Logging in...",
|
||||||
|
"auth_register_button": "Register",
|
||||||
|
"auth_register_button_loading": "Creating account...",
|
||||||
|
"auth_email_label": "Email",
|
||||||
|
"auth_email_placeholder": "Enter your email",
|
||||||
|
"auth_email_address_label": "Email Address",
|
||||||
|
"auth_password_label": "Password",
|
||||||
|
"auth_password_confirm_label": "Confirm Password",
|
||||||
|
"auth_forgot_password": "Forgot password?",
|
||||||
|
"auth_no_account": "Don't have an account?",
|
||||||
|
"auth_have_account": "Already have an account?",
|
||||||
|
"auth_create_account": "Create Account",
|
||||||
|
"auth_create_account_title": "Create Account",
|
||||||
|
"auth_create_account_subtitle": "Join us to start shortening links",
|
||||||
|
"auth_welcome_back": "Welcome Back",
|
||||||
|
"auth_welcome_back_subtitle": "Sign in to continue",
|
||||||
|
"auth_back_to_login": "Back to login",
|
||||||
|
"auth_go_to_login": "Go to login",
|
||||||
|
"auth_remember_password": "Remember your password?",
|
||||||
|
"auth_username_auto": "Username will be generated automatically",
|
||||||
|
"auth_registration_tip": "You'll receive a verification email",
|
||||||
|
"auth_registration_success": "Registration successful!",
|
||||||
|
"auth_registration_success_message": "Please check your email to verify your account.",
|
||||||
|
|
||||||
|
"auth_reset_password_title": "Reset Password",
|
||||||
|
"auth_reset_password_subtitle": "Enter your email to receive a reset link",
|
||||||
|
"auth_reset_password_button": "Reset Password",
|
||||||
|
"auth_reset_password_button_loading": "Resetting...",
|
||||||
|
"auth_send_reset_button": "Send Reset Link",
|
||||||
|
"auth_send_reset_button_loading": "Sending...",
|
||||||
|
"auth_reset_email_sent_title": "Email Sent",
|
||||||
|
"auth_reset_email_sent_message": "Check your inbox for the password reset link.",
|
||||||
|
"auth_request_new_reset_link": "Request new link",
|
||||||
|
|
||||||
|
"auth_set_new_password_title": "Set New Password",
|
||||||
|
"auth_set_new_password_subtitle": "Enter your new password below",
|
||||||
|
"auth_new_password_label": "New Password",
|
||||||
|
"auth_new_password_placeholder": "Enter new password",
|
||||||
|
"auth_confirm_new_password_label": "Confirm New Password",
|
||||||
|
"auth_confirm_new_password_placeholder": "Confirm new password",
|
||||||
|
"auth_password_reset_success": "Password Reset",
|
||||||
|
"auth_password_reset_success_message": "Your password has been successfully reset.",
|
||||||
|
|
||||||
|
"auth_invalid_reset_link": "Invalid Reset Link",
|
||||||
|
"auth_invalid_reset_link_message": "This password reset link is invalid or has expired.",
|
||||||
|
"auth_invalid_verification_link": "Invalid Verification Link",
|
||||||
|
"auth_invalid_verification_link_message": "This verification link is invalid or has expired.",
|
||||||
|
"auth_verification_link_expired": "Link Expired",
|
||||||
|
"auth_verification_link_expired_message": "This verification link has expired. Please request a new one.",
|
||||||
|
"auth_email_verified": "Email Verified",
|
||||||
|
"auth_email_verified_message": "Your email has been successfully verified.",
|
||||||
|
"auth_email_already_verified": "Already Verified",
|
||||||
|
"auth_email_already_verified_message": "Your email is already verified.",
|
||||||
|
"auth_email_already_verified_notify": "Already verified",
|
||||||
|
"auth_email_already_verified_notify_desc": "Your email was already verified. You can log in now.",
|
||||||
|
"auth_token_expired_notify": "Session Expired",
|
||||||
|
"auth_token_expired_notify_desc": "Your session has expired. Please log in again.",
|
||||||
|
|
||||||
|
"auth_add_account": "Add Account",
|
||||||
|
"auth_add_account_info": "Add another account to quickly switch between them",
|
||||||
|
"auth_add_account_subtitle": "Sign in with another account",
|
||||||
|
"auth_add_account_switch_info": "You can switch between accounts anytime",
|
||||||
|
|
||||||
|
"account_my_account": "My Account",
|
||||||
|
"account_add_account": "Add Account",
|
||||||
|
"account_team_accounts": "Team Accounts",
|
||||||
|
"account_no_team_accounts": "No team accounts",
|
||||||
|
"account_team_invite_info": "Invite team members to collaborate",
|
||||||
|
"account_team_member": "Team Member",
|
||||||
|
|
||||||
|
"workspace_switch": "Switch Workspace",
|
||||||
|
"workspace_personal": "Personal",
|
||||||
|
"workspace_create": "Create Workspace",
|
||||||
|
|
||||||
|
"hero_control_headline": "Share Links Smarter",
|
||||||
|
"hero_control_subheadline": "Create shortened links with analytics and QR codes",
|
||||||
|
"hero_control_cta": "Get Started",
|
||||||
|
"hero_free_text": "Free to start",
|
||||||
|
"hero_trust_badge_": "Trusted by thousands",
|
||||||
|
"hero_a": "Hero A",
|
||||||
|
"hero_b": "Hero B",
|
||||||
|
"hero_c": "Hero C",
|
||||||
|
|
||||||
|
"toast_login_success": "Login successful",
|
||||||
|
"toast_login_error": "Login failed",
|
||||||
|
"toast_logout_success": "Logged out successfully",
|
||||||
|
"toast_register_success": "Account created successfully",
|
||||||
|
"toast_link_created": "Link created successfully",
|
||||||
|
"toast_link_updated": "Link updated successfully",
|
||||||
|
"toast_link_deleted": "Link deleted successfully",
|
||||||
|
"toast_link_copied": "Link copied to clipboard",
|
||||||
|
"toast_profile_updated": "Profile updated successfully",
|
||||||
|
"toast_avatar_uploaded": "Avatar uploaded successfully",
|
||||||
|
"toast_password_changed": "Password changed successfully",
|
||||||
|
"toast_password_reset_sent": "Password reset email sent",
|
||||||
|
"toast_email_verified": "Email verified successfully",
|
||||||
|
"toast_session_expired": "Session expired",
|
||||||
|
"toast_session_expired_desc": "Please log in again to continue.",
|
||||||
|
"toast_network_error": "Network error",
|
||||||
|
"toast_network_error_desc": "Please check your connection and try again.",
|
||||||
|
"toast_permission_denied": "Permission denied",
|
||||||
|
"toast_payment_failed": "Payment failed",
|
||||||
|
"toast_payment_failed_desc": "Please try again or use a different payment method.",
|
||||||
|
"toast_subscription_upgraded": "Subscription upgraded",
|
||||||
|
"toast_subscription_cancelled": "Subscription cancelled",
|
||||||
|
"toast_unsupported_format": "Unsupported format",
|
||||||
|
|
||||||
|
"error_link_creation": "Failed to create links",
|
||||||
|
"error_link_creation_single": "Failed to create link",
|
||||||
|
"error_password_change": "Failed to change password",
|
||||||
|
"error_save": "Failed to save changes"
|
||||||
|
}
|
||||||
28
uload/apps/web/src/lib/i18n/locales/es.json
Normal file
28
uload/apps/web/src/lib/i18n/locales/es.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"nav_login": "Iniciar sesión",
|
||||||
|
"nav_register": "Registrarse",
|
||||||
|
"nav_dashboard": "Panel",
|
||||||
|
"nav_folders": "Carpetas",
|
||||||
|
"nav_profile": "Perfil",
|
||||||
|
"nav_logout": "Cerrar sesión",
|
||||||
|
"home_title": "Comparte Enlaces de Forma Inteligente",
|
||||||
|
"home_subtitle": "Crea enlaces acortados con códigos QR, nombres personalizados y análisis",
|
||||||
|
"home_url_label_qr": "URL para codificar",
|
||||||
|
"home_url_label": "URL para acortar",
|
||||||
|
"home_title_label": "Título",
|
||||||
|
"home_title_placeholder": "Dale un nombre a tu enlace",
|
||||||
|
"home_description_label": "Descripción",
|
||||||
|
"home_description_placeholder": "Añadir una descripción (opcional)",
|
||||||
|
"home_expires_label": "Vencimiento",
|
||||||
|
"home_expires_placeholder": "ej., 7 días, 1 mes",
|
||||||
|
"home_max_clicks_label": "Clics máximos",
|
||||||
|
"home_max_clicks_placeholder": "Limitar número de clics",
|
||||||
|
"home_password_label": "Contraseña",
|
||||||
|
"home_password_placeholder": "Proteger con contraseña",
|
||||||
|
"home_guest_info": "Estás usando uload como invitado",
|
||||||
|
"auth_modal_signin": "Iniciar sesión",
|
||||||
|
"home_guest_signin_hint": "para acceder a funciones avanzadas",
|
||||||
|
"home_processing": "Procesando...",
|
||||||
|
"home_submit_button_qr": "Generar Código QR",
|
||||||
|
"home_submit_button": "Crear Enlace"
|
||||||
|
}
|
||||||
28
uload/apps/web/src/lib/i18n/locales/fr.json
Normal file
28
uload/apps/web/src/lib/i18n/locales/fr.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"nav_login": "Connexion",
|
||||||
|
"nav_register": "S'inscrire",
|
||||||
|
"nav_dashboard": "Tableau de bord",
|
||||||
|
"nav_folders": "Dossiers",
|
||||||
|
"nav_profile": "Profil",
|
||||||
|
"nav_logout": "Déconnexion",
|
||||||
|
"home_title": "Partagez des Liens Intelligemment",
|
||||||
|
"home_subtitle": "Créez des liens raccourcis avec codes QR, noms personnalisés et analyses",
|
||||||
|
"home_url_label_qr": "URL à encoder",
|
||||||
|
"home_url_label": "URL à raccourcir",
|
||||||
|
"home_title_label": "Titre",
|
||||||
|
"home_title_placeholder": "Donnez un nom à votre lien",
|
||||||
|
"home_description_label": "Description",
|
||||||
|
"home_description_placeholder": "Ajouter une description (optionnel)",
|
||||||
|
"home_expires_label": "Expiration",
|
||||||
|
"home_expires_placeholder": "ex., 7 jours, 1 mois",
|
||||||
|
"home_max_clicks_label": "Clics maximum",
|
||||||
|
"home_max_clicks_placeholder": "Limiter le nombre de clics",
|
||||||
|
"home_password_label": "Mot de passe",
|
||||||
|
"home_password_placeholder": "Protéger avec mot de passe",
|
||||||
|
"home_guest_info": "Vous utilisez uload en tant qu'invité",
|
||||||
|
"auth_modal_signin": "Se connecter",
|
||||||
|
"home_guest_signin_hint": "pour accéder aux fonctionnalités avancées",
|
||||||
|
"home_processing": "Traitement...",
|
||||||
|
"home_submit_button_qr": "Générer Code QR",
|
||||||
|
"home_submit_button": "Créer Lien"
|
||||||
|
}
|
||||||
28
uload/apps/web/src/lib/i18n/locales/it.json
Normal file
28
uload/apps/web/src/lib/i18n/locales/it.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"nav_login": "Accedi",
|
||||||
|
"nav_register": "Registrati",
|
||||||
|
"nav_dashboard": "Dashboard",
|
||||||
|
"nav_folders": "Cartelle",
|
||||||
|
"nav_profile": "Profilo",
|
||||||
|
"nav_logout": "Esci",
|
||||||
|
"home_title": "Condividi Link in Modo Intelligente",
|
||||||
|
"home_subtitle": "Crea link abbreviati con codici QR, nomi personalizzati e analisi",
|
||||||
|
"home_url_label_qr": "URL da codificare",
|
||||||
|
"home_url_label": "URL da abbreviare",
|
||||||
|
"home_title_label": "Titolo",
|
||||||
|
"home_title_placeholder": "Dai un nome al tuo link",
|
||||||
|
"home_description_label": "Descrizione",
|
||||||
|
"home_description_placeholder": "Aggiungi una descrizione (opzionale)",
|
||||||
|
"home_expires_label": "Scadenza",
|
||||||
|
"home_expires_placeholder": "es., 7 giorni, 1 mese",
|
||||||
|
"home_max_clicks_label": "Click massimi",
|
||||||
|
"home_max_clicks_placeholder": "Limita il numero di click",
|
||||||
|
"home_password_label": "Password",
|
||||||
|
"home_password_placeholder": "Proteggi con password",
|
||||||
|
"home_guest_info": "Stai usando uload come ospite",
|
||||||
|
"auth_modal_signin": "Accedi",
|
||||||
|
"home_guest_signin_hint": "per accedere alle funzionalità avanzate",
|
||||||
|
"home_processing": "Elaborazione...",
|
||||||
|
"home_submit_button_qr": "Genera Codice QR",
|
||||||
|
"home_submit_button": "Crea Link"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { setLocale, getLocale } from '$paraglide/runtime.js';
|
import { locale } from 'svelte-i18n';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import '$lib/i18n'; // Initialize i18n
|
||||||
|
|
||||||
export function initLocale() {
|
export function initLocale() {
|
||||||
if (browser) {
|
if (browser) {
|
||||||
|
|
@ -16,18 +18,25 @@ export function initLocale() {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLocale(targetLang as any, { reload: false });
|
locale.set(targetLang);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Failed to set locale:', e);
|
console.warn('Failed to set locale:', e);
|
||||||
setLocale('en' as any, { reload: false });
|
locale.set('en');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentLocale() {
|
export function getCurrentLocale(): string {
|
||||||
try {
|
try {
|
||||||
return getLocale();
|
return get(locale) || 'en';
|
||||||
} catch {
|
} catch {
|
||||||
return 'en';
|
return 'en';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setCurrentLocale(lang: string) {
|
||||||
|
locale.set(lang);
|
||||||
|
if (browser) {
|
||||||
|
localStorage.setItem('preferred-language', lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
175
uload/apps/web/src/paraglide/messages.ts
Normal file
175
uload/apps/web/src/paraglide/messages.ts
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
// Compatibility layer: Paraglide-style API using svelte-i18n
|
||||||
|
// This allows existing code using m.key() to work with svelte-i18n
|
||||||
|
import { _, locale } from 'svelte-i18n';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import '$lib/i18n'; // Initialize i18n
|
||||||
|
|
||||||
|
// Create a Proxy that returns translation functions for any key
|
||||||
|
const messageProxy = new Proxy(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
get(_target, prop: string) {
|
||||||
|
// Return a function that gets the translation
|
||||||
|
return () => {
|
||||||
|
const translate = get(_);
|
||||||
|
return translate(prop);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) as Record<string, () => string>;
|
||||||
|
|
||||||
|
// Export everything from the proxy
|
||||||
|
export const {
|
||||||
|
// Navigation
|
||||||
|
nav_login,
|
||||||
|
nav_register,
|
||||||
|
nav_dashboard,
|
||||||
|
nav_folders,
|
||||||
|
nav_profile,
|
||||||
|
nav_logout,
|
||||||
|
nav_pricing,
|
||||||
|
|
||||||
|
// Home
|
||||||
|
home_title,
|
||||||
|
home_subtitle,
|
||||||
|
home_url_label_qr,
|
||||||
|
home_url_label,
|
||||||
|
home_title_label,
|
||||||
|
home_title_placeholder,
|
||||||
|
home_description_label,
|
||||||
|
home_description_placeholder,
|
||||||
|
home_expires_label,
|
||||||
|
home_expires_placeholder,
|
||||||
|
home_max_clicks_label,
|
||||||
|
home_max_clicks_placeholder,
|
||||||
|
home_password_label,
|
||||||
|
home_password_placeholder,
|
||||||
|
home_guest_info,
|
||||||
|
home_guest_signin_hint,
|
||||||
|
home_processing,
|
||||||
|
home_submit_button_qr,
|
||||||
|
home_submit_button,
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
auth_modal_signin,
|
||||||
|
auth_sign_in,
|
||||||
|
auth_login_button,
|
||||||
|
auth_login_button_loading,
|
||||||
|
auth_register_button,
|
||||||
|
auth_register_button_loading,
|
||||||
|
auth_email_label,
|
||||||
|
auth_email_placeholder,
|
||||||
|
auth_email_address_label,
|
||||||
|
auth_password_label,
|
||||||
|
auth_password_confirm_label,
|
||||||
|
auth_forgot_password,
|
||||||
|
auth_no_account,
|
||||||
|
auth_have_account,
|
||||||
|
auth_create_account,
|
||||||
|
auth_create_account_title,
|
||||||
|
auth_create_account_subtitle,
|
||||||
|
auth_welcome_back,
|
||||||
|
auth_welcome_back_subtitle,
|
||||||
|
auth_back_to_login,
|
||||||
|
auth_go_to_login,
|
||||||
|
auth_remember_password,
|
||||||
|
auth_username_auto,
|
||||||
|
auth_registration_tip,
|
||||||
|
auth_registration_success,
|
||||||
|
auth_registration_success_message,
|
||||||
|
auth_reset_password_title,
|
||||||
|
auth_reset_password_subtitle,
|
||||||
|
auth_reset_password_button,
|
||||||
|
auth_reset_password_button_loading,
|
||||||
|
auth_send_reset_button,
|
||||||
|
auth_send_reset_button_loading,
|
||||||
|
auth_reset_email_sent_title,
|
||||||
|
auth_reset_email_sent_message,
|
||||||
|
auth_request_new_reset_link,
|
||||||
|
auth_set_new_password_title,
|
||||||
|
auth_set_new_password_subtitle,
|
||||||
|
auth_new_password_label,
|
||||||
|
auth_new_password_placeholder,
|
||||||
|
auth_confirm_new_password_label,
|
||||||
|
auth_confirm_new_password_placeholder,
|
||||||
|
auth_password_reset_success,
|
||||||
|
auth_password_reset_success_message,
|
||||||
|
auth_invalid_reset_link,
|
||||||
|
auth_invalid_reset_link_message,
|
||||||
|
auth_invalid_verification_link,
|
||||||
|
auth_invalid_verification_link_message,
|
||||||
|
auth_verification_link_expired,
|
||||||
|
auth_verification_link_expired_message,
|
||||||
|
auth_email_verified,
|
||||||
|
auth_email_verified_message,
|
||||||
|
auth_email_already_verified,
|
||||||
|
auth_email_already_verified_message,
|
||||||
|
auth_email_already_verified_notify,
|
||||||
|
auth_email_already_verified_notify_desc,
|
||||||
|
auth_token_expired_notify,
|
||||||
|
auth_token_expired_notify_desc,
|
||||||
|
auth_add_account,
|
||||||
|
auth_add_account_info,
|
||||||
|
auth_add_account_subtitle,
|
||||||
|
auth_add_account_switch_info,
|
||||||
|
|
||||||
|
// Account
|
||||||
|
account_my_account,
|
||||||
|
account_add_account,
|
||||||
|
account_team_accounts,
|
||||||
|
account_no_team_accounts,
|
||||||
|
account_team_invite_info,
|
||||||
|
account_team_member,
|
||||||
|
|
||||||
|
// Workspace
|
||||||
|
workspace_switch,
|
||||||
|
workspace_personal,
|
||||||
|
workspace_create,
|
||||||
|
|
||||||
|
// Hero
|
||||||
|
hero_control_headline,
|
||||||
|
hero_control_subheadline,
|
||||||
|
hero_control_cta,
|
||||||
|
hero_free_text,
|
||||||
|
hero_trust_badge_,
|
||||||
|
hero_a,
|
||||||
|
hero_b,
|
||||||
|
hero_c,
|
||||||
|
|
||||||
|
// Toast
|
||||||
|
toast_login_success,
|
||||||
|
toast_login_error,
|
||||||
|
toast_logout_success,
|
||||||
|
toast_register_success,
|
||||||
|
toast_link_created,
|
||||||
|
toast_link_updated,
|
||||||
|
toast_link_deleted,
|
||||||
|
toast_link_copied,
|
||||||
|
toast_profile_updated,
|
||||||
|
toast_avatar_uploaded,
|
||||||
|
toast_password_changed,
|
||||||
|
toast_password_reset_sent,
|
||||||
|
toast_email_verified,
|
||||||
|
toast_session_expired,
|
||||||
|
toast_session_expired_desc,
|
||||||
|
toast_network_error,
|
||||||
|
toast_network_error_desc,
|
||||||
|
toast_permission_denied,
|
||||||
|
toast_payment_failed,
|
||||||
|
toast_payment_failed_desc,
|
||||||
|
toast_subscription_upgraded,
|
||||||
|
toast_subscription_cancelled,
|
||||||
|
toast_unsupported_format,
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
error_link_creation,
|
||||||
|
error_link_creation_single,
|
||||||
|
error_password_change,
|
||||||
|
error_save
|
||||||
|
} = messageProxy;
|
||||||
|
|
||||||
|
// Re-export locale utilities
|
||||||
|
export { locale };
|
||||||
|
|
||||||
|
// Default export for `import * as m from`
|
||||||
|
export default messageProxy;
|
||||||
|
|
@ -4,7 +4,7 @@ services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.simple
|
dockerfile: Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- '3000:3000'
|
- '3000:3000'
|
||||||
environment:
|
environment:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue