Translation pipeline: translate tool, YAML-driven language infrastructure, auto-dispatch
- Add tools/translate: MiniMax/GPT-oss draft → GLM 5 review pipeline via OpenRouter
Supports 10 templates + YAML, 21 languages, provider routing (Fireworks/Groq)
- portal/main.go: render() auto-picks localized templates (page_xx.tmpl)
Removes per-handler Lookup boilerplate from landing/pricing/faq handlers
- base.tmpl: dynamic language dropdown from {{.Languages}}, current lang first
- en.yaml: lang_* keys define all 22 languages (YAML-driven, no hardcoded lists)
- All existing YAMLs: added language_name key
- New: tr.yaml (Turkish), translated templates for de/es/nl/da/ja
- Makefile: translate build target
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
155d24ec2e
commit
7cbca827b3
19
Makefile
19
Makefile
|
|
@ -13,10 +13,10 @@ FIPS := GOFIPS140=v1.0.0
|
|||
BINDIR := bin
|
||||
DEPLOY_DIR := /tank/inou
|
||||
|
||||
.PHONY: all clean deploy deploy-prod sync linux lab tools help list fips-check check-db test test-rbac import-dicom import-genome import-lab nuke-imaging decrypt
|
||||
.PHONY: all clean deploy deploy-prod sync linux lab tools help list fips-check check-db test test-rbac import-dicom import-renpho import-lab nuke-imaging decrypt
|
||||
|
||||
# Default: build everything
|
||||
all: linux lab $(BINDIR)/import-genome $(BINDIR)/import-dicom $(BINDIR)/import-lab $(BINDIR)/nuke-imaging
|
||||
all: linux lab $(BINDIR)/import-renpho $(BINDIR)/import-dicom $(BINDIR)/import-lab $(BINDIR)/nuke-imaging
|
||||
|
||||
# Linux binaries (native, FIPS)
|
||||
linux: $(BINDIR)/viewer $(BINDIR)/portal $(BINDIR)/api
|
||||
|
|
@ -39,11 +39,6 @@ $(BINDIR)/lab-scrape: ./scrape_mychart/main.go | $(BINDIR)
|
|||
$(BINDIR)/lab-import: ./scrape_mychart/import.go | $(BINDIR)
|
||||
$(FIPS) go build $(LDFLAGS) -o $@ ./scrape_mychart/import.go
|
||||
|
||||
# Genome import tool
|
||||
import-genome: $(BINDIR)/import-genome
|
||||
$(BINDIR)/import-genome: ./import-genome/*.go ./lib/*.go | $(BINDIR)
|
||||
$(FIPS) go build $(LDFLAGS) -o $@ ./import-genome
|
||||
|
||||
# DICOM import tool
|
||||
import-dicom: $(BINDIR)/import-dicom
|
||||
$(BINDIR)/import-dicom: ./import-dicom/*.go ./lib/*.go | $(BINDIR)
|
||||
|
|
@ -65,7 +60,7 @@ $(BINDIR)/import-lab: ./cmd/import-lab/*.go ./lib/*.go | $(BINDIR)
|
|||
$(FIPS) go build $(LDFLAGS) -o $@ ./cmd/import-lab
|
||||
|
||||
# Debug tools (no FIPS needed)
|
||||
tools: $(BINDIR)/decrypt $(BINDIR)/fips-check $(BINDIR)/dbquery $(BINDIR)/toolkit
|
||||
tools: $(BINDIR)/decrypt $(BINDIR)/fips-check $(BINDIR)/dbquery $(BINDIR)/toolkit $(BINDIR)/translate
|
||||
|
||||
decrypt: $(BINDIR)/decrypt
|
||||
$(BINDIR)/decrypt: ./tools/decrypt/*.go ./lib/*.go | $(BINDIR)
|
||||
|
|
@ -79,6 +74,10 @@ toolkit: $(BINDIR)/toolkit
|
|||
$(BINDIR)/toolkit: ./tools/toolkit/*.go ./lib/*.go | $(BINDIR)
|
||||
go build -o $@ ./tools/toolkit
|
||||
|
||||
translate: $(BINDIR)/translate
|
||||
$(BINDIR)/translate: ./tools/translate/*.go | $(BINDIR)
|
||||
go build -o $@ ./tools/translate
|
||||
|
||||
fips-check: $(BINDIR)/fips-check
|
||||
$(BINDIR)/fips-check: ./tools/fips-check/*.go | $(BINDIR)
|
||||
go build -o $@ ./tools/fips-check
|
||||
|
|
@ -120,7 +119,7 @@ deploy-prod: check-db all $(BINDIR)/decrypt $(BINDIR)/fips-check
|
|||
ssh $(PROD_HOST) "$(DEPLOY_DIR)/stop.sh"
|
||||
ssh $(PROD_HOST) "mkdir -p $(DEPLOY_DIR)/bin $(DEPLOY_DIR)/templates $(DEPLOY_DIR)/static $(DEPLOY_DIR)/lang"
|
||||
scp $(BINDIR)/viewer $(BINDIR)/portal $(BINDIR)/api $(PROD_HOST):$(DEPLOY_DIR)/bin/
|
||||
scp $(BINDIR)/import-genome $(BINDIR)/import-dicom $(BINDIR)/import-lab $(BINDIR)/nuke-imaging $(BINDIR)/fips-check $(PROD_HOST):$(DEPLOY_DIR)/bin/
|
||||
scp $(BINDIR)/import-renpho $(BINDIR)/import-dicom $(BINDIR)/import-lab $(BINDIR)/nuke-imaging $(BINDIR)/fips-check $(PROD_HOST):$(DEPLOY_DIR)/bin/
|
||||
scp $(BINDIR)/lab-* $(PROD_HOST):$(DEPLOY_DIR)/bin/ 2>/dev/null || true
|
||||
rsync -avz --delete portal/templates/ $(PROD_HOST):$(DEPLOY_DIR)/templates/
|
||||
rsync -avz portal/static/ $(PROD_HOST):$(DEPLOY_DIR)/static/
|
||||
|
|
@ -171,7 +170,7 @@ help:
|
|||
@echo " make check-db - Verify no direct DB access (runs auto on deploy)"
|
||||
@echo " make test - Run integration tests (services must be running)"
|
||||
@echo " make test-rbac - Run RBAC permission tests (API must be running)"
|
||||
@echo " make import-genome - Build genome import tool"
|
||||
@echo " make import-renpho - Build Renpho import tool"
|
||||
@echo " make import-dicom - Build DICOM import tool"
|
||||
@echo " make import-lab - Build lab import tool"
|
||||
@echo " make tools - Build debug tools (decrypt)"
|
||||
|
|
|
|||
|
|
@ -1,196 +1,271 @@
|
|||
language_name: Dansk
|
||||
|
||||
# Landing
|
||||
headline_1: "Dine sundhedsdata."
|
||||
headline_2: "Din AI."
|
||||
headline_3: "Dine svar."
|
||||
intro: "Upload billeddiagnostik, laboratorieresultater og mere. Forbind din AI for at hjælpe dig med at forstå, hvad du ser på."
|
||||
email: "E-mail"
|
||||
get_started: "Kom i gang"
|
||||
data_yours: "Dine data forbliver dine"
|
||||
never_training: "Bruges aldrig til træning"
|
||||
never_training_desc: "Dine billeder bruges aldrig til at træne AI-modeller."
|
||||
never_shared: "Deles aldrig"
|
||||
never_shared_desc: "Vi deler aldrig dine data med nogen."
|
||||
encrypted: "Krypteret lagring"
|
||||
encrypted_desc: "Alle data krypteret i hvile."
|
||||
delete: "Slet når som helst"
|
||||
delete_desc: "Dine data, din kontrol."
|
||||
headline_1: Dine sundhedsdata.
|
||||
headline_2: Din AI.
|
||||
headline_3: Dine svar.
|
||||
intro: Upload billeder, laboratorieprøver og mere. Forbind din AI til at hjælpe dig med at forstå, hvad du kigger på.
|
||||
email: E-mail
|
||||
get_started: Kom i gang
|
||||
data_yours: Dine data forbliver dine
|
||||
never_training: Aldrig brugt til træning
|
||||
never_training_desc: Dine billeder bruges aldrig til at træne AI-modeller.
|
||||
never_shared: Aldrig delt
|
||||
never_shared_desc: Vi deler aldrig dine data med nogen.
|
||||
encrypted: Militærgrads kryptering
|
||||
encrypted_desc: Hvilende og under transport. Dine data rejser aldrig ubeskyttet.
|
||||
delete: Slet når som helst
|
||||
delete_desc: Dine data, din kontrol.
|
||||
|
||||
# Verify
|
||||
check_email: "Tjek din e-mail"
|
||||
code_sent_to: "Vi har sendt en 6-cifret kode til"
|
||||
verification_code: "Bekræftelseskode"
|
||||
verify: "Bekræft"
|
||||
use_different_email: "Brug en anden e-mail"
|
||||
invalid_code: "Ugyldig eller udløbet kode. Prøv igen."
|
||||
check_email: Tjek din e-mail
|
||||
code_sent_to: Vi sendte en 6-cifret kode til
|
||||
verification_code: Verifikationskode
|
||||
verify: Verificér
|
||||
use_different_email: Brug en anden e-mail
|
||||
invalid_code: Ugyldig eller udløbet kode. Prøv igen.
|
||||
|
||||
# Onboard
|
||||
create_dossier: "Opret din dosje"
|
||||
create_profile_intro: "Fortæl os om dig selv for at komme i gang."
|
||||
name: "Navn"
|
||||
name_placeholder: "Dit navn"
|
||||
date_of_birth: "Fødselsdato"
|
||||
sex_at_birth: "Køn ved fødslen"
|
||||
female: "Kvinde"
|
||||
male: "Mand"
|
||||
create_my_dossier: "Opret min dosje"
|
||||
create_dossier: Opret dit dossier
|
||||
create_profile_intro: Fortæl os om dig selv for at komme i gang.
|
||||
name: Navn
|
||||
name_placeholder: Dit navn
|
||||
date_of_birth: Fødselsdato
|
||||
sex_at_birth: Køn ved fødslen
|
||||
female: Kvinde
|
||||
male: Mand
|
||||
create_my_dossier: Opret mit dossier
|
||||
|
||||
# Minor error
|
||||
must_be_18: "Du skal være 18 for at oprette en konto"
|
||||
minor_explanation: "Hvis du opretter dette for en anden, start med din egen profil først. Dette sikrer, at kun du kan få adgang til deres sundhedsdata."
|
||||
minor_next_steps: "Efter at have oprettet din dosje kan du tilføje andre."
|
||||
use_different_dob: "Brug en anden fødselsdato"
|
||||
must_be_18: Du skal være 18 for at oprette en konto
|
||||
minor_explanation: Hvis du opsætter dette for en anden, start med din egen profil først. Dette sikrer, at kun du kan få adgang til deres sundhedsdata.
|
||||
minor_next_steps: Efter at have oprettet dit dossier, kan du tilføje andre.
|
||||
use_different_dob: Brug en anden fødselsdato
|
||||
|
||||
# Minor login block
|
||||
minor_login_blocked: "Du skal være 18 for at logge ind"
|
||||
minor_ask_guardian: "Bed %s om adgang til din dosje."
|
||||
minor_ask_guardian_generic: "Bed en forælder eller værge om adgang til din dosje."
|
||||
minor_login_blocked: "You must be 18 to log in"
|
||||
minor_ask_guardian: "Spørg %s om adgang til dit dossier."
|
||||
minor_ask_guardian_generic: Spørg en forælder eller værge om adgang til dit dossier.
|
||||
|
||||
# Dashboard
|
||||
dossiers: "Dosjer"
|
||||
dossiers_intro: "Administrer sundhedsdata for dig selv eller andre"
|
||||
you: "dig"
|
||||
view: "Vis"
|
||||
save: "Gem"
|
||||
cancel: "Annuller"
|
||||
add_dossier: "Tilføj dosje"
|
||||
edit_dossier: "Rediger dosje"
|
||||
care: "pleje"
|
||||
logout: "Log ud"
|
||||
dossiers: Dossiers
|
||||
dossiers_intro: Administrer sundhedsdata for dig selv eller andre
|
||||
you: dig
|
||||
view: Se
|
||||
save: Gem
|
||||
cancel: Annuller
|
||||
add_dossier: Tilføj dossier
|
||||
edit_dossier: Rediger dossier
|
||||
care: pleje
|
||||
logout: Log ud
|
||||
|
||||
# Profile detail
|
||||
back_to_dossiers: "Tilbage til dosjer"
|
||||
born: "Født"
|
||||
no_access_yet: "Kun du har adgang."
|
||||
people_with_access: "Personer med adgang"
|
||||
share_access: "Del adgang"
|
||||
can_edit: "kan tilføje data"
|
||||
remove: "Fjern"
|
||||
back_to_dossiers: Tilbage til dossiers
|
||||
born: Født
|
||||
no_access_yet: Kun du har adgang.
|
||||
people_with_access: Personer med adgang
|
||||
share_access: Del adgang
|
||||
manage_permissions: Administrer tilladelser
|
||||
can_edit: kan tilføje data
|
||||
remove: Fjern
|
||||
confirm_revoke: "Fjern adgang?"
|
||||
|
||||
# Dossier sections
|
||||
section_imaging: "Billeddiagnostik"
|
||||
section_labs: "Lab"
|
||||
section_uploads: "Uploads"
|
||||
section_vitals: "Vitale tegn"
|
||||
section_medications: "Medicin"
|
||||
section_records: "Journaler"
|
||||
section_journal: "Dagbog"
|
||||
section_genetics: "Genetik"
|
||||
section_privacy: "Privatliv"
|
||||
section_imaging: Billeddiagnostik
|
||||
section_labs: Laboratorier
|
||||
section_uploads: Uploads
|
||||
section_vitals: Værdier
|
||||
section_medications: Medicin
|
||||
section_records: Journaler
|
||||
section_journal: Journal
|
||||
section_checkin: Daglig Check-in
|
||||
section_procedures: Procedurer
|
||||
section_assessments: Vurderinger
|
||||
section_genetics: Genetik
|
||||
section_supplements: Kosttilskud
|
||||
section_symptoms: Symptomer
|
||||
section_hospitalizations: Indlæggelser
|
||||
section_therapies: Terapier
|
||||
section_consultations: Konsultationer
|
||||
section_diagnoses: Diagnoser
|
||||
section_exercise: Motion
|
||||
section_nutrition: Ernæring
|
||||
section_fertility: Frugtbarhed
|
||||
section_notes: Noter
|
||||
section_history: Sygdomshistorie
|
||||
section_family_history: Familiehistorik
|
||||
section_birth: Fødsel
|
||||
section_devices: Enheder
|
||||
section_providers: Udbudere
|
||||
section_questions: Spørgsmål
|
||||
section_privacy: Privatliv
|
||||
|
||||
# Daily Check-in
|
||||
checkin_summary: Spor vitale værdier, medicin, symptomer
|
||||
checkin_build_profile: Tilføj det, du vil spore
|
||||
btn_vitals: Værdier
|
||||
btn_medications: Medicin
|
||||
btn_supplements: Kosttilskud
|
||||
btn_exercise: Motion
|
||||
|
||||
# Plural forms (use %d for count)
|
||||
slice_one: "%d slice"
|
||||
slice_other: "%d slices"
|
||||
series_one: "%d serie"
|
||||
series_other: "%d serier"
|
||||
order_one: "%d ordre"
|
||||
order_other: "%d ordrer"
|
||||
result_one: "%d resultat"
|
||||
result_other: "%d resultater"
|
||||
|
||||
# Section summaries
|
||||
imaging_summary: "%d undersøgelser · %d snit"
|
||||
no_imaging: "Ingen billeddata"
|
||||
no_lab_data: "Ingen labdata"
|
||||
no_genetics: "Ingen genetiske data"
|
||||
no_files: "Ingen filer"
|
||||
no_upload_access: "You don't have permission to upload"
|
||||
imaging_summary: "%d undersøgelser · %d slices"
|
||||
no_imaging: Ingen billeddata
|
||||
no_lab_data: Ingen laboratoriedata
|
||||
no_files: Ingen filer
|
||||
no_upload_access: Du har ikke tilladelse til at uploade
|
||||
files_summary: "%d filer (%s)"
|
||||
series_count: "%d serier"
|
||||
vitals_desc: "Blodtryk, puls, SpO₂, vægt, blodsukker"
|
||||
medications_desc: "Recepter og kosttilskud"
|
||||
records_desc: "Kliniske noter og journaler"
|
||||
journal_desc: "Symptomer, smerte og observationer"
|
||||
vitals_desc: Blodtryk, puls, SpO₂, vægt, glukose
|
||||
medications_desc: Recepter og kosttilskud
|
||||
records_desc: Kliniske noter og journaler
|
||||
journal_desc: Symptomer, smerter og observationer
|
||||
|
||||
# Buttons and actions
|
||||
open_viewer: "Åbn visning"
|
||||
manage: "Administrer"
|
||||
open: Åbn
|
||||
open_viewer: Åbn viewer
|
||||
manage: Administrer
|
||||
show_all_studies: "Vis alle %d undersøgelser..."
|
||||
coming_soon: "Kommer snart"
|
||||
coming_soon: Kommer snart
|
||||
|
||||
# Upload page
|
||||
upload_files: "Upload sundhedsdata"
|
||||
upload_files_intro: "Upload medicinsk billeddiagnostik, laboratorieresultater, genomfiler eller sundhedsrelaterede dokumenter."
|
||||
upload_hint_broad: "DICOM, PDF, CSV, VCF og mere"
|
||||
uploading: "Uploader..."
|
||||
files_uploaded: "filer uploadet"
|
||||
upload_scans: "Upload scanninger"
|
||||
upload_scans_intro: "Upload en mappe med DICOM-filer fra din billedundersøgelse."
|
||||
upload_drop: "Klik eller træk en mappe hertil"
|
||||
upload_hint: "Kun DICOM-mapper"
|
||||
upload_files: Upload sundhedsdata
|
||||
upload_files_intro: Upload medicinsk billeddiagnostik, laboratorieresultater, genomfiler eller andre sundhedsrelaterede dokumenter.
|
||||
upload_hint_broad: DICOM, PDF, CSV, VCF og mere
|
||||
uploading: Uploader...
|
||||
files_uploaded: filer uploadet
|
||||
upload_scans: Upload scans
|
||||
upload_scans_intro: Upload en mappe med DICOM-filer fra din billedundersøgelse.
|
||||
upload_drop: Klik eller træk en mappe her
|
||||
upload_hint: Kun DICOM-mapper
|
||||
|
||||
# Add profile
|
||||
add_dossier_intro: "Tilføj nogen, hvis sundhedsdata du vil administrere."
|
||||
email_optional: "E-mail (valgfrit)"
|
||||
email_optional_hint: "Hvis de er 18, kan de logge ind selv"
|
||||
your_relation: "Dit forhold til dem"
|
||||
select_relation: "Vælg..."
|
||||
i_provide_care: "Jeg yder pleje til denne person"
|
||||
i_am_their: "Jeg er deres..."
|
||||
add_dossier_intro: Tilføj nogen, hvis sundhedsdata du vil administrere.
|
||||
email_optional: E-mail (valgfrit)
|
||||
email_optional_hint: Hvis de er 18+, kan de logge ind selv
|
||||
your_relation: Din relation til dem
|
||||
select_relation: Vælg relation...
|
||||
i_provide_care: Jeg giver pleje til denne person
|
||||
|
||||
# Share access
|
||||
share_access_intro: "Inviter nogen til at få adgang"
|
||||
their_relation: "Deres forhold til denne person"
|
||||
can_add_data: "Kan tilføje data (kosttilskud, noter, osv.)"
|
||||
send_invitation: "Send invitation"
|
||||
back_to_dossier: "Tilbage til dosje"
|
||||
share_access_intro: Inviter nogen til at få adgang
|
||||
their_relation: Deres relation til denne person
|
||||
can_add_data: Kan tilføje data
|
||||
send_invitation: Send invitation
|
||||
back_to_dossier: Tilbage til dossier
|
||||
|
||||
# Relations
|
||||
my_role: "min rolle"
|
||||
role: "role"
|
||||
|
||||
# Invitation email
|
||||
invite_email_subject: "%s tilføjede dig til inou"
|
||||
invite_email_body: "%s tilføjede din sundhedsdosje til inou, så du kan se og administrere dine medicinske data."
|
||||
invite_email_cta: "Log ind for at se"
|
||||
continue: "Fortsæt"
|
||||
invite_email_subject: "%s har tilføjet dig til inou"
|
||||
invite_email_body: "%s har tilføjet dit sundhedsdossier til inou, så du kan se og administrere dine medicinske data."
|
||||
invite_email_cta: Log ind for at se
|
||||
continue: Fortsæt
|
||||
i_am_their: Jeg er deres...
|
||||
|
||||
# Access management
|
||||
people_with_access_count: "personer med adgang"
|
||||
view_audit_log: "Vis aktivitetslog"
|
||||
export_data: "Download my data"
|
||||
relation_with: "Forhold til"
|
||||
audit_log: "Aktivitetslog"
|
||||
audit_log_intro: "Aktivitetshistorik for"
|
||||
audit_log_desc: "Spor hvem der har haft adgang til eller ændret denne dosje"
|
||||
# Simple relation names (for display)
|
||||
my_role: min rolle
|
||||
role: rolle
|
||||
section_privacy: Privatliv
|
||||
people_with_access_count: personer med adgang
|
||||
view_audit_log: Se revisionslog
|
||||
export_data: Download mine data
|
||||
relation_with: Relation med
|
||||
audit_log: Revisionslog
|
||||
audit_log_intro: Aktivitetshistorik for
|
||||
audit_log_desc: Track hvem der fik adgang til eller redigerede dette dossier
|
||||
|
||||
# Install / Connect
|
||||
install_title: "Forbind til Claude"
|
||||
install_intro: "Opsæt inou-broen for at lade Claude analysere dine sundhedsdata"
|
||||
# Permissions (RBAC)
|
||||
permissions_title: Tilladelser
|
||||
permissions_subtitle: Kontrollér hvem der kan få adgang til dette dossier og hvad de kan gøre
|
||||
current_access: Nuværende adgang
|
||||
grant_access: Giv adgang
|
||||
no_grantees: Ingen andre har adgang til dette dossier.
|
||||
person_email: E-mailadresse
|
||||
person_email_hint: Hvis de ikke har en konto, vil de blive inviteret til at oprette en.
|
||||
person_name: Navn
|
||||
select_role: Vælg en rolle...
|
||||
custom_role: Brugerdefinerede tilladelser
|
||||
permissions: Tilladelser
|
||||
op_read: Læs
|
||||
op_write: Skriv
|
||||
op_delete: Slet
|
||||
op_manage: Administrer
|
||||
grant: Giv adgang
|
||||
revoke: Tilbagekald
|
||||
role_descriptions: Rollebeskrivelser
|
||||
ops_legend: Tilladelsesforklaring
|
||||
op_read_desc: Se data
|
||||
op_write_desc: Tilføj/rediger data
|
||||
op_delete_desc: Fjern data
|
||||
op_manage_desc: Administrer hvem der har adgang
|
||||
permissions_updated: Tilladelser opdateret succesfuldt.
|
||||
back: Tilbage
|
||||
can_add_data: Kan tilføje data
|
||||
install_title: Forbind til Claude
|
||||
install_intro: Sæt inou bridge op for at lade Claude analysere dine sundhedsdata
|
||||
install_step1: "Trin 1: Download"
|
||||
install_step1_desc: "Hent broen til din platform"
|
||||
install_download_intro: "Download inou-broen til dit operativsystem:"
|
||||
install_step1_desc: Hent bridge til din platform
|
||||
install_download_intro: "Download inou bridge til dit operativsystem:"
|
||||
install_step2: "Trin 2: Konfigurer"
|
||||
install_step2_desc: "Tilføj til Claude Desktop-konfigurationen"
|
||||
install_config_intro: "Tilføj dette til din Claude Desktop-konfigurationsfil:"
|
||||
install_step2_desc: Tilføj til Claude Desktop config
|
||||
install_config_intro: "Tilføj dette til din Claude Desktop konfigurationsfil:"
|
||||
install_step3: "Trin 3: Test"
|
||||
install_step3_desc: "Bekræft forbindelsen"
|
||||
install_test_intro: "Genstart Claude Desktop og spørg: 'Vis mig mine inou-profiler'"
|
||||
nav_install: "Forbind til Claude"
|
||||
nav_home: "Hjem"
|
||||
install_step3_desc: Verificer forbindelsen
|
||||
install_test_intro: "Genstart Claude Desktop og spørg: 'Vis mig mine inou profiler'"
|
||||
nav_install: Forbind til Claude
|
||||
nav_home: Hjem
|
||||
pending: afventer
|
||||
rate_limit_exceeded: For mange tilmeldingsforsøg fra din placering. Prøv igen i morgen.
|
||||
section_genetics: Genetik
|
||||
no_genetics: Ingen genetiske data
|
||||
|
||||
# Status
|
||||
pending: "afventer"
|
||||
rate_limit_exceeded: "For mange tilmeldingsforsøg fra din placering. Prøv igen i morgen."
|
||||
|
||||
# Sex display
|
||||
sex_0: "ukendt"
|
||||
sex_1: "mand"
|
||||
sex_2: "kvinde"
|
||||
sex_9: "andet"
|
||||
sex_0: ukendt
|
||||
sex_1: mand
|
||||
sex_2: kvinde
|
||||
sex_9: andet
|
||||
|
||||
# Friend invite email
|
||||
friend_invite_subject: "Tjek dette ud — %s"
|
||||
friend_invite_p1: "Jeg bruger <strong>inou</strong>, den sikre måde at opbevare sundhedsdata og udforske dem med AI. Det holder al min families sundhedsinformation ét sted — billedstudier, laboratorieresultater, journaler — og jeg tænkte, det måske også kunne være nyttigt for dig."
|
||||
friend_invite_p2: "Den virkelige styrke ligger i at kunne bruge AI til at forstå det hele: forstå hvad en rapport faktisk betyder, opdage tendenser over tid, eller bare stille spørgsmål på almindeligt dansk og få klare svar."
|
||||
friend_invite_btn: "Opdag inou"
|
||||
friend_invite_dear: "Hej %s,"
|
||||
rel_0: "du"
|
||||
rel_1: "Forælder"
|
||||
rel_2: "Barn"
|
||||
rel_3: "Ægtefælle"
|
||||
rel_4: "Søskende"
|
||||
rel_5: "Værge"
|
||||
rel_6: "Omsorgsgiver"
|
||||
rel_7: "Coach"
|
||||
rel_8: "Læge"
|
||||
rel_9: "Ven"
|
||||
rel_10: "Andet"
|
||||
rel_98: "Andet"
|
||||
rel_99: "Demo"
|
||||
select_relation: "Vælg relation..."
|
||||
friend_invite_p1: "Jeg har brugt <strong>inou</strong>, den sikre måde at opbevare sundhedsdata og udforske dem med AI. Det holder al min families sundhedsoplysninger ét sted — billedundersøgelser, laboratorieresultater, journaler — og jeg tænkte, du måske også ville finde det nyttigt."
|
||||
friend_invite_p2: "Den virkelige styrke er at kunne bruge AI til at give det hele mening: forstå, hvad en rapport faktisk betyder, spotte tendenser over tid, eller bare stille spørgsmål i almindeligt sprog og få klare svar."
|
||||
friend_invite_btn: Tjek inou ud
|
||||
friend_invite_dear: "Kære %s,"
|
||||
rel_0: dig
|
||||
rel_1: Forælder
|
||||
rel_2: Barn
|
||||
rel_3: Ægtefælle
|
||||
rel_4: Søskende
|
||||
rel_5: Værge
|
||||
rel_6: Omsorgsperson
|
||||
rel_7: Coach
|
||||
rel_8: Læge
|
||||
rel_9: Ven
|
||||
rel_10: Andet
|
||||
rel_98: Andet
|
||||
rel_99: Demo
|
||||
select_relation: Vælg relation...
|
||||
audit_dossier_added: "Nyt dossier for %s oprettet af %s"
|
||||
audit_dossier_edited: "Dossier %s redigeret af %s"
|
||||
audit_access_granted: "Adgang til %s givet til %s"
|
||||
audit_dossier_created: "Konto oprettet af %s"
|
||||
audit_access_revoked: "Adgang for %s til %s tilbagekaldt"
|
||||
audit_file_upload: "Fil %s uploadet af %s"
|
||||
audit_file_delete: "Fil %s slettet af %s"
|
||||
audit_file_category_change: "Fil %s kategori ændret af %s"
|
||||
audit_genome_import: "%s genetiske varianter importeret"
|
||||
|
||||
# Kategorier
|
||||
# Categories (category000 = imaging, etc.)
|
||||
category000: Billeddiagnostik
|
||||
category001: Dokument
|
||||
category002: Laboratorieresultat
|
||||
|
|
@ -198,44 +273,68 @@ category003: Genom
|
|||
category004: Upload
|
||||
category005: Konsultation
|
||||
category006: Diagnose
|
||||
category007: Billedresultat
|
||||
category008: EEG-resultat
|
||||
category009: Vitalværdi
|
||||
category007: Billeddiagnostisk fund
|
||||
category008: EEG-fund
|
||||
category009: Vitalparameter
|
||||
category010: Motion
|
||||
category011: Medicin
|
||||
category012: Tilskud
|
||||
category012: Kosttilskud
|
||||
category013: Ernæring
|
||||
category014: Fertilitet
|
||||
category014: Frugtbarhed
|
||||
category015: Symptom
|
||||
category016: Note
|
||||
category017: Sygehistorie
|
||||
category018: Familiehistorie
|
||||
category017: Sygdomshistorie
|
||||
category018: Familiehistorik
|
||||
category019: Kirurgi
|
||||
category020: Hospitalsindlæggelse
|
||||
category021: Fødselsdata
|
||||
category020: Indlæggelse
|
||||
category021: Fødselsjournal
|
||||
category022: Medicinsk udstyr
|
||||
category023: Terapi
|
||||
category024: Vurdering
|
||||
category025: Sundhedsudbyder
|
||||
category025: Udbuder
|
||||
category026: Spørgsmål
|
||||
|
||||
# Genome
|
||||
genome_english_only: "Al genetisk information er på engelsk. Brug Claude til at diskutere det på dansk."
|
||||
genome_variants: "varianter"
|
||||
genome_hidden: "skjulte"
|
||||
genome_english_only: ""
|
||||
genome_variants: varianter
|
||||
genome_hidden: skjult
|
||||
genome_show_all_categories: "Vis alle %d kategorier"
|
||||
|
||||
# API
|
||||
api_token: "API Token"
|
||||
api_token_use: "[EN] Use this token to authenticate API requests:"
|
||||
api_token_warning: "[EN] Keep this private. Anyone with this token can access your health data."
|
||||
api_token_none: "[EN] Generate a token to access the API programmatically or connect AI assistants."
|
||||
api_token_generate: "Generate Token"
|
||||
api_token_regenerate: "Regenerate Token"
|
||||
api_token_regenerate_confirm: "[EN] This will invalidate your current token. Any connected apps will need to be updated."
|
||||
api_authentication: "Authentication"
|
||||
api_auth_instructions: "[EN] Include your API token in the Authorization header:"
|
||||
copy: "Copy"
|
||||
relation: "Relation"
|
||||
relation_to: "Til"
|
||||
me: "Mig"
|
||||
api_token: API-token
|
||||
api_token_use: "Brug denne token til at godkende API-anmodninger:"
|
||||
api_token_warning: Hold dette privat. Alle med denne token kan få adgang til dine sundhedsdata.
|
||||
api_token_none: "Generer en token for at få adgang til API'et programmatisk eller forbinde AI-assistenter."
|
||||
api_token_generate: Generer token
|
||||
api_token_regenerate: Regenerer token
|
||||
api_token_regenerate_confirm: Dette ugyldiggør din nuværende token. Alle forbundne apps skal opdateres.
|
||||
api_authentication: Godkendelse
|
||||
api_auth_instructions: "Inkluder din API-token i Authorization-headeren:"
|
||||
copy: Kopiér
|
||||
relation: Relation
|
||||
relation_to: Til
|
||||
me: Mig
|
||||
|
||||
# Languages (native names — do not translate)
|
||||
lang_da: Dansk
|
||||
lang_de: Deutsch
|
||||
lang_en: English
|
||||
lang_es: Español
|
||||
lang_fi: Suomi
|
||||
lang_fr: Français
|
||||
lang_hi: हिन्दी
|
||||
lang_id: Bahasa Indonesia
|
||||
lang_it: Italiano
|
||||
lang_ja: 日本語
|
||||
lang_ko: 한국어
|
||||
lang_nl: Nederlands
|
||||
lang_no: Norsk
|
||||
lang_pl: Polski
|
||||
lang_pt: Português
|
||||
lang_ru: Русский
|
||||
lang_sv: Svenska
|
||||
lang_th: ไทย
|
||||
lang_tr: Türkçe
|
||||
lang_uk: Українська
|
||||
lang_vi: Tiếng Việt
|
||||
lang_zh: 中文
|
||||
|
|
|
|||
|
|
@ -1,196 +1,271 @@
|
|||
language_name: Deutsch
|
||||
|
||||
# Landing
|
||||
headline_1: "Ihre Gesundheitsdaten."
|
||||
headline_2: "Ihre KI."
|
||||
headline_3: "Ihre Antworten."
|
||||
intro: "Laden Sie Bildgebung, Laborergebnisse und mehr hoch. Verbinden Sie Ihre KI, um zu verstehen, was Sie sehen."
|
||||
email: "E-Mail"
|
||||
get_started: "Loslegen"
|
||||
data_yours: "Ihre Daten bleiben Ihre"
|
||||
never_training: "Nie für Training verwendet"
|
||||
never_training_desc: "Ihre Bilder werden nie zum Trainieren von KI-Modellen verwendet."
|
||||
never_shared: "Nie geteilt"
|
||||
never_shared_desc: "Wir teilen Ihre Daten mit niemandem."
|
||||
encrypted: "Verschlüsselte Speicherung"
|
||||
encrypted_desc: "Alle Daten werden verschlüsselt gespeichert."
|
||||
delete: "Jederzeit löschen"
|
||||
delete_desc: "Ihre Daten, Ihre Kontrolle."
|
||||
headline_1: Deine Gesundheitsdaten.
|
||||
headline_2: Deine KI.
|
||||
headline_3: Deine Antworten.
|
||||
intro: Lade Bildgebung, Laborwerte und mehr hoch. Verbinde deine KI, um dir zu helfen zu verstehen, was du anschaust.
|
||||
email: E-Mail
|
||||
get_started: Loslegen
|
||||
data_yours: Deine Daten bleiben deine
|
||||
never_training: Nie für Training verwendet
|
||||
never_training_desc: Deine Bilder werden niemals zum Trainieren von KI-Modellen verwendet.
|
||||
never_shared: Nie geteilt
|
||||
never_shared_desc: Wir teilen deine Daten nie mit irgendjemandem.
|
||||
encrypted: Militärische Verschlüsselung
|
||||
encrypted_desc: Ruhend und unterwegs. Deine Daten reisen nie ungeschützt.
|
||||
delete: Jederzeit löschen
|
||||
delete_desc: Deine Daten, deine Kontrolle.
|
||||
|
||||
# Verify
|
||||
check_email: "Überprüfen Sie Ihre E-Mail"
|
||||
code_sent_to: "Wir haben einen 6-stelligen Code gesendet an"
|
||||
verification_code: "Bestätigungscode"
|
||||
verify: "Bestätigen"
|
||||
use_different_email: "Andere E-Mail verwenden"
|
||||
invalid_code: "Ungültiger oder abgelaufener Code. Bitte versuchen Sie es erneut."
|
||||
check_email: Überprüfe deine E-Mail
|
||||
code_sent_to: Wir haben einen 6-stelligen Code gesendet an
|
||||
verification_code: Verifizierungscode
|
||||
verify: Verifizieren
|
||||
use_different_email: Andere E-Mail verwenden
|
||||
invalid_code: Ungültiger oder abgelaufener Code. Bitte versuche es erneut.
|
||||
|
||||
# Onboard
|
||||
create_dossier: "Erstellen Sie Ihr Dossier"
|
||||
create_profile_intro: "Erzählen Sie uns von sich, um loszulegen."
|
||||
name: "Name"
|
||||
name_placeholder: "Ihr Name"
|
||||
date_of_birth: "Geburtsdatum"
|
||||
sex_at_birth: "Geschlecht bei Geburt"
|
||||
female: "Weiblich"
|
||||
male: "Männlich"
|
||||
create_my_dossier: "Mein Dossier erstellen"
|
||||
create_dossier: Erstelle dein Dossier
|
||||
create_profile_intro: Erzähl uns etwas über dich, um loszulegen.
|
||||
name: Name
|
||||
name_placeholder: Dein Name
|
||||
date_of_birth: Geburtsdatum
|
||||
sex_at_birth: Geschlecht bei Geburt
|
||||
female: Weiblich
|
||||
male: Männlich
|
||||
create_my_dossier: Mein Dossier erstellen
|
||||
|
||||
# Minor error
|
||||
must_be_18: "Sie müssen 18 sein, um ein Konto zu erstellen"
|
||||
minor_explanation: "Wenn Sie dies für jemand anderen einrichten, beginnen Sie zuerst mit Ihrem eigenen Profil. So stellen Sie sicher, dass nur Sie auf deren Gesundheitsdaten zugreifen können."
|
||||
minor_next_steps: "Nach der Erstellung Ihres Dossiers können Sie weitere hinzufügen."
|
||||
use_different_dob: "Anderes Geburtsdatum verwenden"
|
||||
must_be_18: Du musst 18 sein, um ein Konto zu erstellen
|
||||
minor_explanation: Wenn du dies für jemand anderen einrichtest, beginne zuerst mit deinem eigenen Profil. Dies stellt sicher, dass nur du auf ihre Gesundheitsdaten zugreifen kannst.
|
||||
minor_next_steps: Nach dem Erstellen deines Dossiers kannst du andere hinzufügen.
|
||||
use_different_dob: Anderes Geburtsdatum verwenden
|
||||
|
||||
# Minor login block
|
||||
minor_login_blocked: "Sie müssen 18 sein, um sich anzumelden"
|
||||
minor_ask_guardian: "Bitten Sie %s, auf Ihr Dossier zuzugreifen."
|
||||
minor_ask_guardian_generic: "Bitten Sie einen Elternteil oder Vormund, auf Ihr Dossier zuzugreifen."
|
||||
minor_login_blocked: Du musst 18 sein, um dich anzumelden
|
||||
minor_ask_guardian: "Frage %s, um auf dein Dossier zuzugreifen."
|
||||
minor_ask_guardian_generic: Frage einen Elternteil oder Erziehungsberechtigten, um auf dein Dossier zuzugreifen.
|
||||
|
||||
# Dashboard
|
||||
dossiers: "Dossiers"
|
||||
dossiers_intro: "Verwalten Sie Gesundheitsdaten für sich selbst oder andere"
|
||||
you: "Sie"
|
||||
view: "Ansehen"
|
||||
save: "Speichern"
|
||||
cancel: "Abbrechen"
|
||||
add_dossier: "Dossier hinzufügen"
|
||||
edit_dossier: "Dossier bearbeiten"
|
||||
care: "Pflege"
|
||||
logout: "Abmelden"
|
||||
dossiers: Dossiers
|
||||
dossiers_intro: Verwalte Gesundheitsdaten für dich oder andere
|
||||
you: du
|
||||
view: Ansehen
|
||||
save: Speichern
|
||||
cancel: Abbrechen
|
||||
add_dossier: Dossier hinzufügen
|
||||
edit_dossier: Dossier bearbeiten
|
||||
care: Pflege
|
||||
logout: Abmelden
|
||||
|
||||
# Profile detail
|
||||
back_to_dossiers: "Zurück zu Dossiers"
|
||||
born: "Geboren"
|
||||
no_access_yet: "Nur Sie haben Zugriff."
|
||||
people_with_access: "Personen mit Zugriff"
|
||||
share_access: "Zugriff teilen"
|
||||
can_edit: "kann Daten hinzufügen"
|
||||
remove: "Entfernen"
|
||||
confirm_revoke: "Zugriff entfernen?"
|
||||
back_to_dossiers: Zurück zu Dossiers
|
||||
born: Geboren
|
||||
no_access_yet: Nur du hast Zugriff.
|
||||
people_with_access: Personen mit Zugriff
|
||||
share_access: Zugriff teilen
|
||||
manage_permissions: Berechtigungen verwalten
|
||||
can_edit: kann Daten hinzufügen
|
||||
remove: Entfernen
|
||||
confirm_revoke: "Zugriff entziehen?"
|
||||
|
||||
# Dossier sections
|
||||
section_imaging: "Bildgebung"
|
||||
section_labs: "Labor"
|
||||
section_uploads: "Uploads"
|
||||
section_vitals: "Vitalwerte"
|
||||
section_medications: "Medikamente"
|
||||
section_records: "Unterlagen"
|
||||
section_journal: "Tagebuch"
|
||||
section_genetics: "Genetik"
|
||||
section_privacy: "Datenschutz"
|
||||
section_imaging: Bildgebung
|
||||
section_labs: Laborwerte
|
||||
section_uploads: Uploads
|
||||
section_vitals: Vitalwerte
|
||||
section_medications: Medikamente
|
||||
section_records: Aufzeichnungen
|
||||
section_journal: Tagebuch
|
||||
section_checkin: Tägliches Check-in
|
||||
section_procedures: Eingriffe
|
||||
section_assessments: Bewertungen
|
||||
section_genetics: Genetik
|
||||
section_supplements: Nahrungsergänzungsmittel
|
||||
section_symptoms: Symptome
|
||||
section_hospitalizations: Krankenhausaufenthalte
|
||||
section_therapies: Therapien
|
||||
section_consultations: Konsultationen
|
||||
section_diagnoses: Diagnosen
|
||||
section_exercise: Sport
|
||||
section_nutrition: Ernährung
|
||||
section_fertility: Fruchtbarkeit
|
||||
section_notes: Notizen
|
||||
section_history: Krankengeschichte
|
||||
section_family_history: Familienanamnese
|
||||
section_birth: Geburt
|
||||
section_devices: Geräte
|
||||
section_providers: Anbieter
|
||||
section_questions: Fragen
|
||||
section_privacy: Datenschutz
|
||||
|
||||
# Daily Check-in
|
||||
checkin_summary: Tracke Vitalwerte, Medikamente, Symptome
|
||||
checkin_build_profile: Füge hinzu, was du tracken möchtest
|
||||
btn_vitals: Vitalwerte
|
||||
btn_medications: Medikamente
|
||||
btn_supplements: Nahrungsergänzungsmittel
|
||||
btn_exercise: Sport
|
||||
|
||||
# Plural forms (use %d for count)
|
||||
slice_one: "%d Slice"
|
||||
slice_other: "%d Slices"
|
||||
series_one: "%d Serie"
|
||||
series_other: "%d Serien"
|
||||
order_one: "%d Bestellung"
|
||||
order_other: "%d Bestellungen"
|
||||
result_one: "%d Ergebnis"
|
||||
result_other: "%d Ergebnisse"
|
||||
|
||||
# Section summaries
|
||||
imaging_summary: "%d Studien · %d Schichten"
|
||||
no_imaging: "Keine Bildgebungsdaten"
|
||||
no_lab_data: "Keine Labordaten"
|
||||
no_genetics: "Keine genetischen Daten"
|
||||
no_files: "Keine Dateien"
|
||||
no_upload_access: "You don't have permission to upload"
|
||||
imaging_summary: "%d Studien · %d Slices"
|
||||
no_imaging: Keine Bildgebungsdaten
|
||||
no_lab_data: Keine Laborwerte
|
||||
no_files: Keine Dateien
|
||||
no_upload_access: Du hast keine Berechtigung zum Hochladen
|
||||
files_summary: "%d Dateien (%s)"
|
||||
series_count: "%d Serien"
|
||||
vitals_desc: "Blutdruck, Herzfrequenz, SpO₂, Gewicht, Glukose"
|
||||
medications_desc: "Rezepte und Nahrungsergänzungsmittel"
|
||||
records_desc: "Klinische Notizen und Krankenakten"
|
||||
journal_desc: "Symptome, Schmerzen und Beobachtungen"
|
||||
vitals_desc: Blutdruck, Herzfrequenz, SpO₂, Gewicht, Glukose
|
||||
medications_desc: Rezepte und Nahrungsergänzungsmittel
|
||||
records_desc: Klinische Notizen und medizinische Aufzeichnungen
|
||||
journal_desc: Symptome, Schmerzen und Beobachtungen
|
||||
|
||||
# Buttons and actions
|
||||
open_viewer: "Viewer öffnen"
|
||||
manage: "Verwalten"
|
||||
open: Öffnen
|
||||
open_viewer: Viewer öffnen
|
||||
manage: Verwalten
|
||||
show_all_studies: "Alle %d Studien anzeigen..."
|
||||
coming_soon: "Demnächst"
|
||||
coming_soon: Demnächst
|
||||
|
||||
# Upload page
|
||||
upload_files: "Gesundheitsdaten hochladen"
|
||||
upload_files_intro: "Laden Sie medizinische Bildgebung, Laborergebnisse, Genomdateien oder andere gesundheitsbezogene Dokumente hoch."
|
||||
upload_hint_broad: "DICOM, PDF, CSV, VCF und mehr"
|
||||
uploading: "Wird hochgeladen..."
|
||||
files_uploaded: "Dateien hochgeladen"
|
||||
upload_scans: "Scans hochladen"
|
||||
upload_scans_intro: "Laden Sie einen Ordner mit DICOM-Dateien aus Ihrer Bildgebungsstudie hoch."
|
||||
upload_drop: "Klicken oder Ordner hierher ziehen"
|
||||
upload_hint: "Nur DICOM-Ordner"
|
||||
upload_files: Gesundheitsdaten hochladen
|
||||
upload_files_intro: Lade medizinische Bildgebung, Laborergebnisse, Genomdateien oder beliebige gesundheitsbezogene Dokumente hoch.
|
||||
upload_hint_broad: DICOM, PDF, CSV, VCF und mehr
|
||||
uploading: Wird hochgeladen...
|
||||
files_uploaded: Dateien hochgeladen
|
||||
upload_scans: Scans hochladen
|
||||
upload_scans_intro: Lade einen Ordner mit DICOM-Dateien von deiner Bildgebungsstudie hoch.
|
||||
upload_drop: Klicke oder ziehe einen Ordner hierher
|
||||
upload_hint: Nur DICOM-Ordner
|
||||
|
||||
# Add profile
|
||||
add_dossier_intro: "Fügen Sie jemanden hinzu, dessen Gesundheitsdaten Sie verwalten möchten."
|
||||
email_optional: "E-Mail (optional)"
|
||||
email_optional_hint: "Wenn sie 18 sind, können sie sich selbst anmelden"
|
||||
your_relation: "Ihre Beziehung zu dieser Person"
|
||||
select_relation: "Auswählen..."
|
||||
i_provide_care: "Ich pflege diese Person"
|
||||
i_am_their: "Ich bin deren..."
|
||||
add_dossier_intro: Füge jemanden hinzu, dessen Gesundheitsdaten du verwalten möchtest.
|
||||
email_optional: E-Mail (optional)
|
||||
email_optional_hint: Wenn sie 18+ sind, können sie sich selbst einloggen
|
||||
your_relation: Deine Beziehung zu ihnen
|
||||
select_relation: Beziehung auswählen...
|
||||
i_provide_care: Ich pflege diese Person
|
||||
|
||||
# Share access
|
||||
share_access_intro: "Jemanden zum Zugriff einladen"
|
||||
their_relation: "Deren Beziehung zu dieser Person"
|
||||
can_add_data: "Kann Daten hinzufügen (Nahrungsergänzungsmittel, Notizen, usw.)"
|
||||
send_invitation: "Einladung senden"
|
||||
back_to_dossier: "Zurück zum Dossier"
|
||||
share_access_intro: Jemanden einladen, zuzugreifen
|
||||
their_relation: Ihre Beziehung zu dieser Person
|
||||
can_add_data: Kann Daten hinzufügen
|
||||
send_invitation: Einladung senden
|
||||
back_to_dossier: Zurück zum Dossier
|
||||
|
||||
# Relations
|
||||
my_role: "meine Rolle"
|
||||
role: "role"
|
||||
|
||||
# Invitation email
|
||||
invite_email_subject: "%s hat Sie zu inou hinzugefügt"
|
||||
invite_email_body: "%s hat Ihr Gesundheitsdossier zu inou hinzugefügt, damit Sie Ihre medizinischen Daten einsehen und verwalten können."
|
||||
invite_email_cta: "Anmelden zum Ansehen"
|
||||
continue: "Weiter"
|
||||
invite_email_subject: "%s hat dich zu inou hinzugefügt"
|
||||
invite_email_body: "%s hat dein Gesundheitsdossier zu inou hinzugefügt, damit du deine medizinischen Daten ansehen und verwalten kannst."
|
||||
invite_email_cta: Anmelden zum Ansehen
|
||||
continue: Weiter
|
||||
i_am_their: Ich bin ihr/e...
|
||||
|
||||
# Access management
|
||||
people_with_access_count: "Personen mit Zugriff"
|
||||
view_audit_log: "Aktivitätsprotokoll ansehen"
|
||||
export_data: "Download my data"
|
||||
relation_with: "Beziehung zu"
|
||||
audit_log: "Aktivitätsprotokoll"
|
||||
audit_log_intro: "Aktivitätsverlauf für"
|
||||
audit_log_desc: "Verfolgen Sie, wer auf dieses Dossier zugegriffen oder es geändert hat"
|
||||
# Simple relation names (for display)
|
||||
my_role: meine Rolle
|
||||
role: Rolle
|
||||
section_privacy: Datenschutz
|
||||
people_with_access_count: Personen mit Zugriff
|
||||
view_audit_log: Audit-Protokoll ansehen
|
||||
export_data: Meine Daten herunterladen
|
||||
relation_with: Beziehung mit
|
||||
audit_log: Audit-Protokoll
|
||||
audit_log_intro: Aktivitätsverlauf für
|
||||
audit_log_desc: Verfolge, wer auf dieses Dossier zugegriffen oder es geändert hat
|
||||
|
||||
# Install / Connect
|
||||
install_title: "Mit Claude verbinden"
|
||||
install_intro: "Richten Sie die inou-Bridge ein, damit Claude Ihre Gesundheitsdaten analysieren kann"
|
||||
# Permissions (RBAC)
|
||||
permissions_title: Berechtigungen
|
||||
permissions_subtitle: Kontrolliere, wer auf dieses Dossier zugreifen kann und was sie tun können
|
||||
current_access: Aktueller Zugriff
|
||||
grant_access: Zugriff gewähren
|
||||
no_grantees: Niemand anderes hat Zugriff auf dieses Dossier.
|
||||
person_email: E-Mail-Adresse
|
||||
person_email_hint: Wenn sie kein Konto haben, werden sie eingeladen, eines zu erstellen.
|
||||
person_name: Name
|
||||
select_role: Rolle auswählen...
|
||||
custom_role: Benutzerdefinierte Berechtigungen
|
||||
permissions: Berechtigungen
|
||||
op_read: Lesen
|
||||
op_write: Schreiben
|
||||
op_delete: Löschen
|
||||
op_manage: Verwalten
|
||||
grant: Zugriff gewähren
|
||||
revoke: Widerrufen
|
||||
role_descriptions: Rollenbeschreibungen
|
||||
ops_legend: Berechtigungslegende
|
||||
op_read_desc: Daten ansehen
|
||||
op_write_desc: Daten hinzufügen/bearbeiten
|
||||
op_delete_desc: Daten entfernen
|
||||
op_manage_desc: Verwalte, wer Zugriff hat
|
||||
permissions_updated: Berechtigungen erfolgreich aktualisiert.
|
||||
back: Zurück
|
||||
can_add_data: Kann Daten hinzufügen
|
||||
install_title: Mit Claude verbinden
|
||||
install_intro: Richte die inou Bridge ein, damit Claude deine Gesundheitsdaten analysieren kann
|
||||
install_step1: "Schritt 1: Herunterladen"
|
||||
install_step1_desc: "Laden Sie die Bridge für Ihre Plattform herunter"
|
||||
install_download_intro: "Laden Sie die inou-Bridge für Ihr Betriebssystem herunter:"
|
||||
install_step1_desc: Hole dir die Bridge für deine Plattform
|
||||
install_download_intro: "Lade die inou Bridge für dein Betriebssystem herunter:"
|
||||
install_step2: "Schritt 2: Konfigurieren"
|
||||
install_step2_desc: "Zur Claude Desktop-Konfiguration hinzufügen"
|
||||
install_config_intro: "Fügen Sie dies zu Ihrer Claude Desktop-Konfigurationsdatei hinzu:"
|
||||
install_step2_desc: Zur Claude Desktop Konfiguration hinzufügen
|
||||
install_config_intro: "Füge dies zu deiner Claude Desktop Konfigurationsdatei hinzu:"
|
||||
install_step3: "Schritt 3: Testen"
|
||||
install_step3_desc: "Verbindung überprüfen"
|
||||
install_test_intro: "Starten Sie Claude Desktop neu und fragen Sie: 'Zeige mir meine inou-Profile'"
|
||||
nav_install: "Mit Claude verbinden"
|
||||
nav_home: "Startseite"
|
||||
install_step3_desc: Verifiziere die Verbindung
|
||||
install_test_intro: "Starte Claude Desktop neu und frage: 'Zeig mir meine inou Profile'"
|
||||
nav_install: Mit Claude verbinden
|
||||
nav_home: Startseite
|
||||
pending: ausstehend
|
||||
rate_limit_exceeded: Zu viele Anmeldeversuche von deinem Standort. Bitte versuche es morgen erneut.
|
||||
section_genetics: Genetik
|
||||
no_genetics: Keine genetischen Daten
|
||||
|
||||
# Status
|
||||
pending: "ausstehend"
|
||||
rate_limit_exceeded: "Zu viele Anmeldeversuche von Ihrem Standort. Bitte versuchen Sie es morgen erneut."
|
||||
|
||||
# Sex display
|
||||
sex_0: "unbekannt"
|
||||
sex_1: "männlich"
|
||||
sex_2: "weiblich"
|
||||
sex_9: "andere"
|
||||
sex_0: unbekannt
|
||||
sex_1: männlich
|
||||
sex_2: weiblich
|
||||
sex_9: andere
|
||||
|
||||
# Friend invite email
|
||||
friend_invite_subject: "Schau dir das an — %s"
|
||||
friend_invite_p1: "Ich nutze <strong>inou</strong>, die sichere Art, Gesundheitsdaten zu speichern und mit KI zu erkunden. Es hält alle Gesundheitsinformationen meiner Familie an einem Ort — Bildgebung, Laborergebnisse, Krankenakten — und ich dachte, es könnte auch für dich nützlich sein."
|
||||
friend_invite_p2: "Die wahre Stärke liegt darin, KI nutzen zu können, um alles zu verstehen: zu verstehen, was ein Bericht wirklich bedeutet, Trends über die Zeit zu erkennen, oder einfach Fragen in normaler Sprache zu stellen und klare Antworten zu bekommen."
|
||||
friend_invite_btn: "Entdecke inou"
|
||||
friend_invite_p1: "Ich nutze <strong>inou</strong>, die sichere Methode, um Gesundheitsdaten zu speichern und mit KI zu analysieren. Es speichert alle Gesundheitsinformationen meiner Familie an einem Ort – Bildgebungsstudien, Laborergebnisse, medizinische Aufzeichnungen – und ich dachte, du könntest es auch nützlich finden."
|
||||
friend_invite_p2: "Die wahre Kraft liegt darin, KI nutzen zu können, um alles zu verstehen: verstehe, was ein Bericht wirklich bedeutet, erkenne Trends über Zeit, oder stell einfach Fragen in einfacher Sprache und erhalte klare Antworten."
|
||||
friend_invite_btn: Schau dir inou an
|
||||
friend_invite_dear: "Liebe/r %s,"
|
||||
rel_0: "du"
|
||||
rel_1: "Elternteil"
|
||||
rel_2: "Kind"
|
||||
rel_3: "Ehepartner"
|
||||
rel_4: "Geschwister"
|
||||
rel_5: "Vormund"
|
||||
rel_6: "Betreuer"
|
||||
rel_7: "Coach"
|
||||
rel_8: "Arzt"
|
||||
rel_9: "Freund"
|
||||
rel_10: "Andere"
|
||||
rel_98: "Andere"
|
||||
rel_99: "Demo"
|
||||
select_relation: "Beziehung auswählen..."
|
||||
rel_0: du
|
||||
rel_1: Elternteil
|
||||
rel_2: Kind
|
||||
rel_3: Ehepartner/in
|
||||
rel_4: Geschwister
|
||||
rel_5: Erziehungsberechtigte/r
|
||||
rel_6: Pflegeperson
|
||||
rel_7: Coach
|
||||
rel_8: Arzt/Ärztin
|
||||
rel_9: Freund/in
|
||||
rel_10: Andere/r
|
||||
rel_98: Andere/r
|
||||
rel_99: Demo
|
||||
select_relation: Beziehung auswählen...
|
||||
audit_dossier_added: "Neues Dossier für %s erstellt von %s"
|
||||
audit_dossier_edited: "Dossier %s bearbeitet von %s"
|
||||
audit_access_granted: "Zugriff auf %s gewährt für %s"
|
||||
audit_dossier_created: "Konto erstellt von %s"
|
||||
audit_access_revoked: "Zugriff für %s auf %s widerrufen"
|
||||
audit_file_upload: "Datei %s hochgeladen von %s"
|
||||
audit_file_delete: "Datei %s gelöscht von %s"
|
||||
audit_file_category_change: "Datei %s Kategorie geändert von %s"
|
||||
audit_genome_import: "%s genetische Varianten importiert"
|
||||
|
||||
# Kategorien
|
||||
# Categories (category000 = imaging, etc.)
|
||||
category000: Bildgebung
|
||||
category001: Dokument
|
||||
category002: Laborergebnis
|
||||
|
|
@ -198,12 +273,12 @@ category003: Genom
|
|||
category004: Upload
|
||||
category005: Konsultation
|
||||
category006: Diagnose
|
||||
category007: Bildgebungsergebnis
|
||||
category008: EEG-Ergebnis
|
||||
category009: Vitalwert
|
||||
category010: Bewegung
|
||||
category007: Bildgebungsbefund
|
||||
category008: EEG-Befund
|
||||
category009: Vitalzeichen
|
||||
category010: Sport
|
||||
category011: Medikament
|
||||
category012: Nahrungsergänzung
|
||||
category012: Nahrungsergänzungsmittel
|
||||
category013: Ernährung
|
||||
category014: Fruchtbarkeit
|
||||
category015: Symptom
|
||||
|
|
@ -212,30 +287,54 @@ category017: Krankengeschichte
|
|||
category018: Familienanamnese
|
||||
category019: Operation
|
||||
category020: Krankenhausaufenthalt
|
||||
category021: Geburtsdaten
|
||||
category021: Geburtsurkunde
|
||||
category022: Medizinisches Gerät
|
||||
category023: Therapie
|
||||
category024: Bewertung
|
||||
category025: Gesundheitsdienstleister
|
||||
category025: Anbieter
|
||||
category026: Frage
|
||||
|
||||
# Genome
|
||||
genome_english_only: "Alle genetischen Informationen sind auf Englisch. Verwenden Sie Claude, um sie auf Deutsch zu besprechen."
|
||||
genome_variants: "Varianten"
|
||||
genome_hidden: "verborgen"
|
||||
genome_english_only: ""
|
||||
genome_variants: Varianten
|
||||
genome_hidden: versteckt
|
||||
genome_show_all_categories: "Alle %d Kategorien anzeigen"
|
||||
|
||||
# API
|
||||
api_token: "API Token"
|
||||
api_token_use: "[EN] Use this token to authenticate API requests:"
|
||||
api_token_warning: "[EN] Keep this private. Anyone with this token can access your health data."
|
||||
api_token_none: "[EN] Generate a token to access the API programmatically or connect AI assistants."
|
||||
api_token_generate: "Generate Token"
|
||||
api_token_regenerate: "Regenerate Token"
|
||||
api_token_regenerate_confirm: "[EN] This will invalidate your current token. Any connected apps will need to be updated."
|
||||
api_authentication: "Authentication"
|
||||
api_auth_instructions: "[EN] Include your API token in the Authorization header:"
|
||||
copy: "Copy"
|
||||
relation: "Beziehung"
|
||||
relation_to: "Zu"
|
||||
me: "Ich"
|
||||
api_token: API-Token
|
||||
api_token_use: "Verwende diesen Token für die Authentifizierung von API-Anfragen:"
|
||||
api_token_warning: Bewahre dies privat auf. Jeder mit diesem Token kann auf deine Gesundheitsdaten zugreifen.
|
||||
api_token_none: Generiere einen Token für den programmatischen API-Zugriff oder um KI-Assistenten zu verbinden.
|
||||
api_token_generate: Token generieren
|
||||
api_token_regenerate: Token neu generieren
|
||||
api_token_regenerate_confirm: Dies macht deinen aktuellen Token ungültig. Alle verbundenen Apps müssen aktualisiert werden.
|
||||
api_authentication: Authentifizierung
|
||||
api_auth_instructions: "Füge deinen API-Token in den Authorization-Header ein:"
|
||||
copy: Kopieren
|
||||
relation: Beziehung
|
||||
relation_to: Zu
|
||||
me: Ich
|
||||
|
||||
# Languages (native names — do not translate)
|
||||
lang_da: Dansk
|
||||
lang_de: Deutsch
|
||||
lang_en: English
|
||||
lang_es: Español
|
||||
lang_fi: Suomi
|
||||
lang_fr: Français
|
||||
lang_hi: हिन्दी
|
||||
lang_id: Bahasa Indonesia
|
||||
lang_it: Italiano
|
||||
lang_ja: 日本語
|
||||
lang_ko: 한국어
|
||||
lang_nl: Nederlands
|
||||
lang_no: Norsk
|
||||
lang_pl: Polski
|
||||
lang_pt: Português
|
||||
lang_ru: Русский
|
||||
lang_sv: Svenska
|
||||
lang_th: ไทย
|
||||
lang_tr: Türkçe
|
||||
lang_uk: Українська
|
||||
lang_vi: Tiếng Việt
|
||||
lang_zh: 中文
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: English
|
||||
|
||||
# Landing
|
||||
headline_1: "Your health data."
|
||||
headline_2: "Your AI."
|
||||
|
|
@ -312,3 +314,27 @@ copy: "Copy"
|
|||
relation: "Relation"
|
||||
relation_to: "To"
|
||||
me: "Me"
|
||||
|
||||
# Languages (native names — do not translate)
|
||||
lang_da: Dansk
|
||||
lang_de: Deutsch
|
||||
lang_en: English
|
||||
lang_es: Español
|
||||
lang_fi: Suomi
|
||||
lang_fr: Français
|
||||
lang_hi: हिन्दी
|
||||
lang_id: Bahasa Indonesia
|
||||
lang_it: Italiano
|
||||
lang_ja: 日本語
|
||||
lang_ko: 한국어
|
||||
lang_nl: Nederlands
|
||||
lang_no: Norsk
|
||||
lang_pl: Polski
|
||||
lang_pt: Português
|
||||
lang_ru: Русский
|
||||
lang_sv: Svenska
|
||||
lang_th: ไทย
|
||||
lang_tr: Türkçe
|
||||
lang_uk: Українська
|
||||
lang_vi: Tiếng Việt
|
||||
lang_zh: 中文
|
||||
|
|
|
|||
|
|
@ -1,205 +1,280 @@
|
|||
language_name: Español
|
||||
|
||||
# Landing
|
||||
headline_1: "Tus datos de salud."
|
||||
headline_2: "Tu IA."
|
||||
headline_3: "Tus respuestas."
|
||||
intro: "Sube imágenes médicas, análisis y más. Conecta tu IA para ayudarte a entender lo que estás viendo."
|
||||
email: "Correo electrónico"
|
||||
get_started: "Comenzar"
|
||||
data_yours: "Tus datos son tuyos"
|
||||
never_training: "Nunca usados para entrenamiento"
|
||||
never_training_desc: "Tus imágenes nunca se usan para entrenar modelos de IA."
|
||||
never_shared: "Nunca compartidos"
|
||||
never_shared_desc: "Nunca compartimos tus datos con nadie."
|
||||
encrypted: "Almacenamiento cifrado"
|
||||
encrypted_desc: "Todos los datos cifrados en reposo."
|
||||
delete: "Eliminar en cualquier momento"
|
||||
delete_desc: "Tus datos, tu control."
|
||||
headline_1: Tus datos de salud.
|
||||
headline_2: Tu IA.
|
||||
headline_3: Tus respuestas.
|
||||
intro: Sube imagenología, laboratorios y más. Conecta tu IA para ayudarte a entender lo que estás viendo.
|
||||
email: Correo electrónico
|
||||
get_started: Comenzar
|
||||
data_yours: Tus datos siguen siendo tuyos
|
||||
never_training: Nunca usado para entrenamiento
|
||||
never_training_desc: Tus imágenes nunca se usan para entrenar modelos de IA.
|
||||
never_shared: Nunca compartido
|
||||
never_shared_desc: Nunca compartimos tus datos con nadie.
|
||||
encrypted: Cifrado de grado militar
|
||||
encrypted_desc: En reposo y en tránsito. Tus datos nunca viajan sin protección.
|
||||
delete: Eliminar en cualquier momento
|
||||
delete_desc: Tus datos, tu control.
|
||||
|
||||
# Verify
|
||||
check_email: "Revisa tu correo"
|
||||
code_sent_to: "Enviamos un código de 6 dígitos a"
|
||||
verification_code: "Código de verificación"
|
||||
verify: "Verificar"
|
||||
use_different_email: "Usar otro correo"
|
||||
invalid_code: "Código inválido o expirado. Por favor, inténtalo de nuevo."
|
||||
check_email: Revisa tu correo electrónico
|
||||
code_sent_to: Enviamos un código de 6 dígitos a
|
||||
verification_code: Código de verificación
|
||||
verify: Verificar
|
||||
use_different_email: Usar un correo electrónico diferente
|
||||
invalid_code: Código inválido o expirado. Por favor intenta de nuevo.
|
||||
|
||||
# Onboard
|
||||
create_dossier: "Crea tu expediente"
|
||||
create_profile_intro: "Cuéntanos sobre ti para comenzar."
|
||||
name: "Nombre"
|
||||
name_placeholder: "Tu nombre"
|
||||
date_of_birth: "Fecha de nacimiento"
|
||||
sex_at_birth: "Sexo al nacer"
|
||||
female: "Femenino"
|
||||
male: "Masculino"
|
||||
create_my_dossier: "Crear mi expediente"
|
||||
create_dossier: Crea tu expediente
|
||||
create_profile_intro: Cuéntanos sobre ti para comenzar.
|
||||
name: Nombre
|
||||
name_placeholder: Tu nombre
|
||||
date_of_birth: Fecha de nacimiento
|
||||
sex_at_birth: Sexo al nacer
|
||||
female: Femenino
|
||||
male: Masculino
|
||||
create_my_dossier: Crear mi expediente
|
||||
|
||||
# Minor error
|
||||
must_be_18: "Debes tener 18 años para crear una cuenta"
|
||||
minor_explanation: "Si estás configurando esto para otra persona, comienza primero con tu propio perfil. Esto asegura que solo tú puedas acceder a sus datos de salud."
|
||||
minor_next_steps: "Después de crear tu expediente, puedes agregar otros."
|
||||
use_different_dob: "Usar otra fecha de nacimiento"
|
||||
must_be_18: Debes tener 18 años para crear una cuenta
|
||||
minor_explanation: Si estás configurando esto para alguien más, comienza con tu propio perfil primero. Esto asegura que solo tú puedas acceder a sus datos de salud.
|
||||
minor_next_steps: Después de crear tu expediente, puedes agregar a otros.
|
||||
use_different_dob: Usar una fecha de nacimiento diferente
|
||||
|
||||
# Minor login block
|
||||
minor_login_blocked: "Debes tener 18 años para iniciar sesión"
|
||||
minor_login_blocked: "You must be 18 to log in"
|
||||
minor_ask_guardian: "Pide a %s que acceda a tu expediente."
|
||||
minor_ask_guardian_generic: "Pide a un padre o tutor que acceda a tu expediente."
|
||||
minor_ask_guardian_generic: Pide a un padre o tutor que acceda a tu expediente.
|
||||
|
||||
# Dashboard
|
||||
dossiers: "Expedientes"
|
||||
dossiers_intro: "Gestiona datos de salud para ti o para otros"
|
||||
you: "tú"
|
||||
view: "Ver"
|
||||
save: "Guardar"
|
||||
cancel: "Cancelar"
|
||||
add_dossier: "Agregar expediente"
|
||||
edit_dossier: "Editar expediente"
|
||||
care: "cuidado"
|
||||
logout: "Cerrar sesión"
|
||||
dossiers: Expedientes
|
||||
dossiers_intro: Gestiona datos de salud para ti o para otros
|
||||
you: tú
|
||||
view: Ver
|
||||
save: Guardar
|
||||
cancel: Cancelar
|
||||
add_dossier: Agregar expediente
|
||||
edit_dossier: Editar expediente
|
||||
care: cuidado
|
||||
logout: Cerrar sesión
|
||||
|
||||
# Profile detail
|
||||
back_to_dossiers: "Volver a expedientes"
|
||||
born: "Nacido/a"
|
||||
no_access_yet: "Solo tú tienes acceso."
|
||||
people_with_access: "Personas con acceso"
|
||||
share_access: "Compartir acceso"
|
||||
can_edit: "puede agregar datos"
|
||||
remove: "Eliminar"
|
||||
back_to_dossiers: Volver a expedientes
|
||||
born: Nacido/a
|
||||
no_access_yet: Solo tú tienes acceso.
|
||||
people_with_access: Personas con acceso
|
||||
share_access: Compartir acceso
|
||||
manage_permissions: Gestionar permisos
|
||||
can_edit: puede agregar datos
|
||||
remove: Eliminar
|
||||
confirm_revoke: "¿Eliminar acceso?"
|
||||
|
||||
# Dossier sections
|
||||
section_imaging: "Imágenes"
|
||||
section_labs: "Laboratorio"
|
||||
section_uploads: "Archivos"
|
||||
section_vitals: "Signos vitales"
|
||||
section_medications: "Medicamentos"
|
||||
section_records: "Registros"
|
||||
section_journal: "Diario"
|
||||
section_genetics: "Genética"
|
||||
section_privacy: "Privacidad"
|
||||
section_imaging: Imagenología
|
||||
section_labs: Laboratorios
|
||||
section_uploads: Subidas
|
||||
section_vitals: Signos vitales
|
||||
section_medications: Medicamentos
|
||||
section_records: Registros
|
||||
section_journal: Diario
|
||||
section_checkin: Registro diario
|
||||
section_procedures: Procedimientos
|
||||
section_assessments: Evaluaciones
|
||||
section_genetics: Genética
|
||||
section_supplements: Suplementos
|
||||
section_symptoms: Síntomas
|
||||
section_hospitalizations: Hospitalizaciones
|
||||
section_therapies: Terapias
|
||||
section_consultations: Consultas
|
||||
section_diagnoses: Diagnósticos
|
||||
section_exercise: Ejercicio
|
||||
section_nutrition: Nutrición
|
||||
section_fertility: Fertilidad
|
||||
section_notes: Notas
|
||||
section_history: Historial médico
|
||||
section_family_history: Historial familiar
|
||||
section_birth: Nacimiento
|
||||
section_devices: Dispositivos
|
||||
section_providers: Proveedores
|
||||
section_questions: Preguntas
|
||||
section_privacy: Privacidad
|
||||
|
||||
# Daily Check-in
|
||||
checkin_summary: Registra signos vitales, medicamentos, síntomas
|
||||
checkin_build_profile: Agrega lo que quieres seguir
|
||||
btn_vitals: Signos vitales
|
||||
btn_medications: Medicamentos
|
||||
btn_supplements: Suplementos
|
||||
btn_exercise: Ejercicio
|
||||
|
||||
# Plural forms (use %d for count)
|
||||
slice_one: "%d corte"
|
||||
slice_other: "%d cortes"
|
||||
series_one: "%d serie"
|
||||
series_other: "%d series"
|
||||
order_one: "%d orden"
|
||||
order_other: "%d órdenes"
|
||||
result_one: "%d resultado"
|
||||
result_other: "%d resultados"
|
||||
|
||||
# Section summaries
|
||||
imaging_summary: "%d estudios · %d cortes"
|
||||
no_imaging: "Sin datos de imágenes"
|
||||
no_lab_data: "Sin datos de laboratorio"
|
||||
no_genetics: "Sin datos genéticos"
|
||||
no_files: "Sin archivos"
|
||||
no_upload_access: "You don't have permission to upload"
|
||||
no_imaging: Sin datos de imagenología
|
||||
no_lab_data: Sin datos de laboratorio
|
||||
no_files: Sin archivos
|
||||
no_upload_access: No tienes permiso para subir
|
||||
files_summary: "%d archivos (%s)"
|
||||
series_count: "%d series"
|
||||
vitals_desc: "Presión arterial, frecuencia cardíaca, SpO₂, peso, glucosa"
|
||||
medications_desc: "Recetas y suplementos"
|
||||
records_desc: "Notas clínicas e historiales médicos"
|
||||
journal_desc: "Síntomas, dolor y observaciones"
|
||||
vitals_desc: Presión arterial, frecuencia cardíaca, SpO₂, peso, glucosa
|
||||
medications_desc: Recetas y suplementos
|
||||
records_desc: Notas clínicas y registros médicos
|
||||
journal_desc: Síntomas, dolor y observaciones
|
||||
|
||||
# Buttons and actions
|
||||
open_viewer: "Abrir visor"
|
||||
manage: "Gestionar"
|
||||
open: Abrir
|
||||
open_viewer: Abrir visor
|
||||
manage: Gestionar
|
||||
show_all_studies: "Mostrar los %d estudios..."
|
||||
coming_soon: "Próximamente"
|
||||
coming_soon: Próximamente
|
||||
|
||||
# Upload page
|
||||
upload_files: "Subir datos de salud"
|
||||
upload_files_intro: "Sube imágenes médicas, resultados de laboratorio, archivos genómicos o cualquier documento relacionado con la salud."
|
||||
upload_hint_broad: "DICOM, PDF, CSV, VCF y más"
|
||||
uploading: "Subiendo..."
|
||||
files_uploaded: "archivos subidos"
|
||||
upload_scans: "Subir estudios"
|
||||
upload_scans_intro: "Sube una carpeta con archivos DICOM de tu estudio de imágenes."
|
||||
upload_drop: "Haz clic o arrastra una carpeta aquí"
|
||||
upload_hint: "Solo carpetas DICOM"
|
||||
upload_files: Subir datos de salud
|
||||
upload_files_intro: Sube imagenología médica, resultados de laboratorio, archivos de genoma o cualquier documento relacionado con la salud.
|
||||
upload_hint_broad: DICOM, PDF, CSV, VCF y más
|
||||
uploading: Subiendo...
|
||||
files_uploaded: archivos subidos
|
||||
upload_scans: Subir escaneos
|
||||
upload_scans_intro: Sube una carpeta que contenga archivos DICOM de tu estudio de imagenología.
|
||||
upload_drop: Haz clic o arrastra una carpeta aquí
|
||||
upload_hint: Solo carpetas DICOM
|
||||
|
||||
# Add profile
|
||||
add_dossier_intro: "Agrega a alguien cuyos datos de salud quieras gestionar."
|
||||
email_optional: "Correo (opcional)"
|
||||
email_optional_hint: "Si tienen 18, pueden iniciar sesión ellos mismos"
|
||||
your_relation: "Tu relación con esta persona"
|
||||
select_relation: "Seleccionar..."
|
||||
i_provide_care: "Proporciono cuidado a esta persona"
|
||||
i_am_their: "Soy su..."
|
||||
add_dossier_intro: Agrega a alguien cuyos datos de salud quieres gestionar.
|
||||
email_optional: Correo electrónico (opcional)
|
||||
email_optional_hint: Si tiene más de 18 años, puede iniciar sesión por sí mismo
|
||||
your_relation: Tu relación con ellos
|
||||
select_relation: Selecciona relación...
|
||||
i_provide_care: Brindo cuidado a esta persona
|
||||
|
||||
# Share access
|
||||
share_access_intro: "Invitar a alguien a acceder"
|
||||
their_relation: "Su relación con esta persona"
|
||||
can_add_data: "Puede agregar datos (suplementos, notas, etc.)"
|
||||
send_invitation: "Enviar invitación"
|
||||
back_to_dossier: "Volver al expediente"
|
||||
share_access_intro: Invita a alguien a acceder
|
||||
their_relation: Su relación con esta persona
|
||||
can_add_data: Puede agregar datos
|
||||
send_invitation: Enviar invitación
|
||||
back_to_dossier: Volver al expediente
|
||||
|
||||
# Relations
|
||||
my_role: "mi rol"
|
||||
role: "role"
|
||||
|
||||
# Invitation email
|
||||
invite_email_subject: "%s te agregó a inou"
|
||||
invite_email_body: "%s agregó tu expediente de salud a inou para que puedas ver y gestionar tus datos médicos."
|
||||
invite_email_cta: "Iniciar sesión para ver"
|
||||
continue: "Continuar"
|
||||
invite_email_cta: Iniciar sesión para ver
|
||||
continue: Continuar
|
||||
i_am_their: Soy su...
|
||||
|
||||
# Access management
|
||||
people_with_access_count: "personas con acceso"
|
||||
view_audit_log: "Ver registro de actividad"
|
||||
export_data: "Download my data"
|
||||
relation_with: "Relación con"
|
||||
audit_log: "Registro de actividad"
|
||||
audit_log_intro: "Historial de actividad para"
|
||||
audit_log_desc: "Rastrea quién accedió o modificó este expediente"
|
||||
# Simple relation names (for display)
|
||||
my_role: mi rol
|
||||
role: rol
|
||||
section_privacy: Privacidad
|
||||
people_with_access_count: personas con acceso
|
||||
view_audit_log: Ver registro de auditoría
|
||||
export_data: Descargar mis datos
|
||||
relation_with: Relación con
|
||||
audit_log: Registro de auditoría
|
||||
audit_log_intro: Historial de actividad para
|
||||
audit_log_desc: Rastrea quién accedió o modificó este expediente
|
||||
|
||||
# Install / Connect
|
||||
install_title: "Conectar con Claude"
|
||||
install_intro: "Configura el puente inou para que Claude analice tus datos de salud"
|
||||
# Permissions (RBAC)
|
||||
permissions_title: Permisos
|
||||
permissions_subtitle: Controla quién puede acceder a este expediente y qué puede hacer
|
||||
current_access: Acceso actual
|
||||
grant_access: Conceder acceso
|
||||
no_grantees: Nadie más tiene acceso a este expediente.
|
||||
person_email: Dirección de correo electrónico
|
||||
person_email_hint: Si no tiene una cuenta, será invitado a crear una.
|
||||
person_name: Nombre
|
||||
select_role: Selecciona un rol...
|
||||
custom_role: Permisos personalizados
|
||||
permissions: Permisos
|
||||
op_read: Leer
|
||||
op_write: Escribir
|
||||
op_delete: Eliminar
|
||||
op_manage: Gestionar
|
||||
grant: Conceder acceso
|
||||
revoke: Revocar
|
||||
role_descriptions: Descripciones de roles
|
||||
ops_legend: Leyenda de permisos
|
||||
op_read_desc: Ver datos
|
||||
op_write_desc: Agregar/editar datos
|
||||
op_delete_desc: Eliminar datos
|
||||
op_manage_desc: Gestionar quién tiene acceso
|
||||
permissions_updated: Permisos actualizados exitosamente.
|
||||
back: Volver
|
||||
can_add_data: Puede agregar datos
|
||||
install_title: Conectar a Claude
|
||||
install_intro: Configura el puente de inou para que Claude analice tus datos de salud
|
||||
install_step1: "Paso 1: Descargar"
|
||||
install_step1_desc: "Obtén el puente para tu plataforma"
|
||||
install_download_intro: "Descarga el puente inou para tu sistema operativo:"
|
||||
install_step1_desc: Obtén el puente para tu plataforma
|
||||
install_download_intro: "Descarga el puente de inou para tu sistema operativo:"
|
||||
install_step2: "Paso 2: Configurar"
|
||||
install_step2_desc: "Agregar a la configuración de Claude Desktop"
|
||||
install_step2_desc: Agregar a la configuración de Claude Desktop
|
||||
install_config_intro: "Agrega esto a tu archivo de configuración de Claude Desktop:"
|
||||
install_step3: "Paso 3: Probar"
|
||||
install_step3_desc: "Verificar la conexión"
|
||||
install_step3_desc: Verifica la conexión
|
||||
install_test_intro: "Reinicia Claude Desktop y pregunta: 'Muéstrame mis perfiles de inou'"
|
||||
nav_install: "Conectar con Claude"
|
||||
nav_home: "Inicio"
|
||||
nav_install: Conectar a Claude
|
||||
nav_home: Inicio
|
||||
pending: pendiente
|
||||
rate_limit_exceeded: Demasiados intentos de registro desde tu ubicación. Por favor intenta de nuevo mañana.
|
||||
section_genetics: Genética
|
||||
no_genetics: Sin datos genéticos
|
||||
|
||||
# Status
|
||||
pending: "pendiente"
|
||||
rate_limit_exceeded: "Demasiados intentos de registro desde tu ubicación. Por favor, inténtalo mañana."
|
||||
|
||||
# Sex display
|
||||
sex_0: "desconocido"
|
||||
sex_1: "masculino"
|
||||
sex_2: "femenino"
|
||||
sex_9: "otro"
|
||||
sex_0: desconocido
|
||||
sex_1: masculino
|
||||
sex_2: femenino
|
||||
sex_9: otro
|
||||
|
||||
# Friend invite email
|
||||
friend_invite_subject: "Mira esto — %s"
|
||||
friend_invite_p1: "Estoy usando <strong>inou</strong>, la forma segura de guardar datos de salud y explorarlos con IA. Mantiene toda la información de salud de mi familia en un solo lugar — estudios de imagen, resultados de laboratorio, historiales médicos — y pensé que también te podría ser útil."
|
||||
friend_invite_p2: "El verdadero poder está en poder usar IA para entenderlo todo: comprender qué significa realmente un informe, detectar tendencias a lo largo del tiempo, o simplemente hacer preguntas en lenguaje sencillo y obtener respuestas claras."
|
||||
friend_invite_btn: "Descubre inou"
|
||||
friend_invite_dear: "Querido/a %s,"
|
||||
rel_0: "tú"
|
||||
rel_1: "Padre/Madre"
|
||||
rel_2: "Hijo/a"
|
||||
rel_3: "Cónyuge"
|
||||
rel_4: "Hermano/a"
|
||||
rel_5: "Tutor"
|
||||
rel_6: "Cuidador"
|
||||
rel_7: "Coach"
|
||||
rel_8: "Médico"
|
||||
rel_9: "Amigo"
|
||||
rel_10: "Otro"
|
||||
rel_98: "Otro"
|
||||
rel_99: "Demo"
|
||||
select_relation: "Seleccionar relación..."
|
||||
friend_invite_subject: "Echa un vistazo a esto — %s"
|
||||
friend_invite_p1: "He estado usando <strong>inou</strong>, la forma segura de almacenar datos de salud y explorarlos con IA. Mantiene toda la información de salud de mi familia en un solo lugar — estudios de imagen, resultados de laboratorio, registros médicos — y pensé que podría serte útil."
|
||||
friend_invite_p2: "El verdadero poder está en poder usar IA para darle sentido a todo: entender lo que realmente significa un informe, detectar tendencias a lo largo del tiempo, o simplemente hacer preguntas en lenguaje cotidiano y obtener respuestas claras."
|
||||
friend_invite_btn: Ver inou
|
||||
friend_invite_dear: "Estimado/a %s,"
|
||||
rel_0: tú
|
||||
rel_1: Padre/Madre
|
||||
rel_2: Hijo/a
|
||||
rel_3: Cónyuge
|
||||
rel_4: Hermano/a
|
||||
rel_5: Tutor
|
||||
rel_6: Cuidador
|
||||
rel_7: Entrenador
|
||||
rel_8: Doctor/a
|
||||
rel_9: Amigo/a
|
||||
rel_10: Otro
|
||||
rel_98: Otro
|
||||
rel_99: Demo
|
||||
select_relation: Selecciona relación...
|
||||
audit_dossier_added: "Nuevo expediente para %s creado por %s"
|
||||
audit_dossier_edited: "Expediente %s editado por %s"
|
||||
audit_access_granted: "Acceso a %s concedido a %s"
|
||||
audit_dossier_created: "Cuenta creada por %s"
|
||||
audit_access_revoked: "Acceso de %s a %s revocado"
|
||||
audit_file_upload: "Archivo %s subido por %s"
|
||||
audit_file_delete: "Archivo %s eliminado por %s"
|
||||
audit_file_category_change: "Categoría del archivo %s cambiada por %s"
|
||||
audit_genome_import: "%s variantes genéticas importadas"
|
||||
|
||||
# Categorías
|
||||
category000: Imagen médica
|
||||
# Categories (category000 = imaging, etc.)
|
||||
category000: Imagenología
|
||||
category001: Documento
|
||||
category002: Resultado de laboratorio
|
||||
category003: Genoma
|
||||
category004: Carga
|
||||
category004: Subida
|
||||
category005: Consulta
|
||||
category006: Diagnóstico
|
||||
category007: Resultado de imagen
|
||||
category008: Resultado de EEG
|
||||
category007: Hallazgo de imagenología
|
||||
category008: Hallazgo de EEG
|
||||
category009: Signo vital
|
||||
category010: Ejercicio
|
||||
category011: Medicamento
|
||||
|
|
@ -209,33 +284,57 @@ category014: Fertilidad
|
|||
category015: Síntoma
|
||||
category016: Nota
|
||||
category017: Historial médico
|
||||
category018: Antecedentes familiares
|
||||
category018: Historial familiar
|
||||
category019: Cirugía
|
||||
category020: Hospitalización
|
||||
category021: Datos de nacimiento
|
||||
category021: Registro de nacimiento
|
||||
category022: Dispositivo médico
|
||||
category023: Terapia
|
||||
category024: Evaluación
|
||||
category025: Proveedor de salud
|
||||
category025: Proveedor
|
||||
category026: Pregunta
|
||||
|
||||
# Genome
|
||||
genome_english_only: "Toda la información genética está en inglés. Usa Claude para discutirla en español."
|
||||
genome_variants: "variantes"
|
||||
genome_hidden: "ocultas"
|
||||
genome_english_only: ""
|
||||
genome_variants: variantes
|
||||
genome_hidden: oculto
|
||||
genome_show_all_categories: "Mostrar las %d categorías"
|
||||
|
||||
# API
|
||||
api_token: "API Token"
|
||||
api_token_use: "[EN] Use this token to authenticate API requests:"
|
||||
api_token_warning: "[EN] Keep this private. Anyone with this token can access your health data."
|
||||
api_token_none: "[EN] Generate a token to access the API programmatically or connect AI assistants."
|
||||
api_token_generate: "Generate Token"
|
||||
api_token_regenerate: "Regenerate Token"
|
||||
api_token_regenerate_confirm: "[EN] This will invalidate your current token. Any connected apps will need to be updated."
|
||||
api_authentication: "Authentication"
|
||||
api_auth_instructions: "[EN] Include your API token in the Authorization header:"
|
||||
copy: "Copy"
|
||||
relation: "Relación"
|
||||
relation_to: "A"
|
||||
me: "Yo"
|
||||
api_token: Token de API
|
||||
api_token_use: "Usa este token para autenticar solicitudes de API:"
|
||||
api_token_warning: Mantén esto en privado. Cualquier persona con este token puede acceder a tus datos de salud.
|
||||
api_token_none: Genera un token para acceder a la API programáticamente o conectar asistentes de IA.
|
||||
api_token_generate: Generar token
|
||||
api_token_regenerate: Regenerar token
|
||||
api_token_regenerate_confirm: Esto invalidará tu token actual. Cualquier aplicación conectada deberá actualizarse.
|
||||
api_authentication: Autenticación
|
||||
api_auth_instructions: "Incluye tu token de API en el encabezado de Authorization:"
|
||||
copy: Copiar
|
||||
relation: Relación
|
||||
relation_to: Con
|
||||
me: Yo
|
||||
|
||||
# Languages (native names — do not translate)
|
||||
lang_da: Dansk
|
||||
lang_de: Deutsch
|
||||
lang_en: English
|
||||
lang_es: Español
|
||||
lang_fi: Suomi
|
||||
lang_fr: Français
|
||||
lang_hi: हिन्दी
|
||||
lang_id: Bahasa Indonesia
|
||||
lang_it: Italiano
|
||||
lang_ja: 日本語
|
||||
lang_ko: 한국어
|
||||
lang_nl: Nederlands
|
||||
lang_no: Norsk
|
||||
lang_pl: Polski
|
||||
lang_pt: Português
|
||||
lang_ru: Русский
|
||||
lang_sv: Svenska
|
||||
lang_th: ไทย
|
||||
lang_tr: Türkçe
|
||||
lang_uk: Українська
|
||||
lang_vi: Tiếng Việt
|
||||
lang_zh: 中文
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Suomi
|
||||
|
||||
# Landing
|
||||
headline_1: "Sinun terveystietosi."
|
||||
headline_2: "Sinun tekoälysi."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Français
|
||||
|
||||
# Landing
|
||||
headline_1: "Vos données de santé."
|
||||
headline_2: "Votre IA."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Italiano
|
||||
|
||||
# Landing
|
||||
headline_1: "I tuoi dati sanitari."
|
||||
headline_2: "La tua IA."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: 日本語
|
||||
|
||||
# Landing
|
||||
headline_1: "あなたの健康データ。"
|
||||
headline_2: "あなたのAI。"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: 한국어
|
||||
|
||||
# Landing
|
||||
headline_1: "당신의 건강 데이터."
|
||||
headline_2: "당신의 AI."
|
||||
|
|
|
|||
|
|
@ -1,27 +1,29 @@
|
|||
language_name: Nederlands
|
||||
|
||||
# Landing
|
||||
headline_1: "Jouw gezondheidsdata."
|
||||
headline_2: "Jouw AI."
|
||||
headline_3: "Jouw antwoorden."
|
||||
intro: "Upload beeldvorming, labresultaten en meer. Verbind je AI om te begrijpen wat je ziet."
|
||||
intro: "Upload beeldvorming, labresultaten en meer. Verbind je AI om te begrijpen waar je naar kijkt."
|
||||
email: "E-mail"
|
||||
get_started: "Aan de slag"
|
||||
data_yours: "Jouw data blijft van jou"
|
||||
data_yours: "Je data blijft van jou"
|
||||
never_training: "Nooit gebruikt voor training"
|
||||
never_training_desc: "Je beelden worden nooit gebruikt om AI-modellen te trainen."
|
||||
never_shared: "Nooit gedeeld"
|
||||
never_shared_desc: "We delen je data nooit met anderen."
|
||||
encrypted: "Versleutelde opslag"
|
||||
encrypted_desc: "Alle data versleuteld opgeslagen."
|
||||
delete: "Altijd verwijderen"
|
||||
never_shared_desc: "We delen je data nooit met wie dan ook."
|
||||
encrypted: "Militaire encryptie"
|
||||
encrypted_desc: "In rust en onderweg. Je data reist nooit onbeschermd."
|
||||
delete: "Verwijder wanneer je wilt"
|
||||
delete_desc: "Jouw data, jouw controle."
|
||||
|
||||
# Verify
|
||||
check_email: "Controleer je e-mail"
|
||||
check_email: "Check je e-mail"
|
||||
code_sent_to: "We hebben een 6-cijferige code gestuurd naar"
|
||||
verification_code: "Verificatiecode"
|
||||
verify: "Verifiëren"
|
||||
use_different_email: "Ander e-mailadres gebruiken"
|
||||
invalid_code: "Ongeldige of verlopen code. Probeer opnieuw."
|
||||
use_different_email: "Gebruik een ander e-mailadres"
|
||||
invalid_code: "Ongeldige of verlopen code. Probeer het opnieuw."
|
||||
|
||||
# Onboard
|
||||
create_dossier: "Maak je dossier aan"
|
||||
|
|
@ -32,13 +34,13 @@ date_of_birth: "Geboortedatum"
|
|||
sex_at_birth: "Geslacht bij geboorte"
|
||||
female: "Vrouw"
|
||||
male: "Man"
|
||||
create_my_dossier: "Mijn dossier aanmaken"
|
||||
create_my_dossier: "Maak mijn dossier aan"
|
||||
|
||||
# Minor error
|
||||
must_be_18: "Je moet 18 zijn om een account aan te maken"
|
||||
minor_explanation: "Als je dit voor iemand anders instelt, begin dan eerst met je eigen profiel. Zo heb alleen jij toegang tot hun gezondheidsgegevens."
|
||||
minor_explanation: "Als je dit voor iemand anders instelt, begin dan met je eigen profiel. Zo heb alleen jij toegang tot hun gezondheidsdata."
|
||||
minor_next_steps: "Na het aanmaken van je dossier kun je anderen toevoegen."
|
||||
use_different_dob: "Andere geboortedatum gebruiken"
|
||||
use_different_dob: "Gebruik een andere geboortedatum"
|
||||
|
||||
# Minor login block
|
||||
minor_login_blocked: "Je moet 18 zijn om in te loggen"
|
||||
|
|
@ -47,7 +49,7 @@ minor_ask_guardian_generic: "Vraag een ouder of voogd om toegang tot je dossier.
|
|||
|
||||
# Dashboard
|
||||
dossiers: "Dossiers"
|
||||
dossiers_intro: "Beheer de gezondheidsgegevens van jezelf of voor anderen"
|
||||
dossiers_intro: "Beheer gezondheidsdata voor jezelf of anderen"
|
||||
you: "jij"
|
||||
view: "Bekijken"
|
||||
save: "Opslaan"
|
||||
|
|
@ -61,25 +63,54 @@ logout: "Uitloggen"
|
|||
back_to_dossiers: "Terug naar dossiers"
|
||||
born: "Geboren"
|
||||
no_access_yet: "Alleen jij hebt toegang."
|
||||
people_with_access: "Personen met toegang"
|
||||
people_with_access: "Mensen met toegang"
|
||||
share_access: "Toegang delen"
|
||||
can_edit: "kan gegevens toevoegen"
|
||||
manage_permissions: "Rechten beheren"
|
||||
can_edit: "kan data toevoegen"
|
||||
remove: "Verwijderen"
|
||||
confirm_revoke: "Toegang intrekken?"
|
||||
|
||||
# Dossier sections
|
||||
section_imaging: "Radiologie"
|
||||
section_imaging: "Beeldvorming"
|
||||
section_labs: "Labresultaten"
|
||||
section_uploads: "Uploads"
|
||||
section_vitals: "Vitale functies"
|
||||
section_vitals: "Vitale waarden"
|
||||
section_medications: "Medicatie"
|
||||
section_records: "Dossiers"
|
||||
section_journal: "Dagboek"
|
||||
section_checkin: "Dagelijkse check-in"
|
||||
section_procedures: "Ingrepen"
|
||||
section_assessments: "Beoordelingen"
|
||||
section_genetics: "Genetica"
|
||||
section_supplements: "Supplementen"
|
||||
section_symptoms: "Symptomen"
|
||||
section_hospitalizations: "Ziekenhuisopnames"
|
||||
section_therapies: "Therapieën"
|
||||
section_consultations: "Consulten"
|
||||
section_diagnoses: "Diagnoses"
|
||||
section_exercise: "Beweging"
|
||||
section_nutrition: "Voeding"
|
||||
section_fertility: "Vruchtbaarheid"
|
||||
section_notes: "Notities"
|
||||
section_history: "Medische geschiedenis"
|
||||
section_family_history: "Familiegeschiedenis"
|
||||
section_birth: "Geboorte"
|
||||
section_devices: "Apparaten"
|
||||
section_providers: "Zorgverleners"
|
||||
section_questions: "Vragen"
|
||||
section_privacy: "Privacy"
|
||||
|
||||
# Section summaries
|
||||
# Plural forms
|
||||
slice_one: "%d beeld"
|
||||
slice_other: "%d beelden"
|
||||
# Daily Check-in
|
||||
checkin_summary: "Houd vitale waarden, medicatie en symptomen bij"
|
||||
checkin_build_profile: "Voeg toe wat je wilt bijhouden"
|
||||
btn_vitals: "Vitale waarden"
|
||||
btn_medications: "Medicatie"
|
||||
btn_supplements: "Supplementen"
|
||||
btn_exercise: "Beweging"
|
||||
|
||||
# Plural forms (use %d for count)
|
||||
slice_one: "%d slice"
|
||||
slice_other: "%d slices"
|
||||
series_one: "%d serie"
|
||||
series_other: "%d series"
|
||||
order_one: "%d aanvraag"
|
||||
|
|
@ -87,11 +118,12 @@ order_other: "%d aanvragen"
|
|||
result_one: "%d resultaat"
|
||||
result_other: "%d resultaten"
|
||||
|
||||
imaging_summary: "%d onderzoeken · %d beelden"
|
||||
# Section summaries
|
||||
imaging_summary: "%d onderzoeken · %d slices"
|
||||
no_imaging: "Geen beeldvorming"
|
||||
no_lab_data: "Geen labresultaten"
|
||||
no_files: "Geen bestanden"
|
||||
no_upload_access: "You don't have permission to upload"
|
||||
no_upload_access: "Je hebt geen rechten om te uploaden"
|
||||
files_summary: "%d bestanden (%s)"
|
||||
series_count: "%d series"
|
||||
vitals_desc: "Bloeddruk, hartslag, SpO₂, gewicht, glucose"
|
||||
|
|
@ -100,13 +132,14 @@ records_desc: "Klinische notities en medische dossiers"
|
|||
journal_desc: "Symptomen, pijn en observaties"
|
||||
|
||||
# Buttons and actions
|
||||
open: "Openen"
|
||||
open_viewer: "Viewer openen"
|
||||
manage: "Beheren"
|
||||
show_all_studies: "Toon alle %d onderzoeken..."
|
||||
coming_soon: "Binnenkort beschikbaar"
|
||||
|
||||
# Upload page
|
||||
upload_files: "Gezondheidsgegevens uploaden"
|
||||
upload_files: "Gezondheidsdata uploaden"
|
||||
upload_files_intro: "Upload medische beeldvorming, labresultaten, genoombestanden of andere gezondheidsgerelateerde documenten."
|
||||
upload_hint_broad: "DICOM, PDF, CSV, VCF en meer"
|
||||
uploading: "Uploaden..."
|
||||
|
|
@ -117,17 +150,17 @@ upload_drop: "Klik of sleep een map hierheen"
|
|||
upload_hint: "Alleen DICOM-mappen"
|
||||
|
||||
# Add profile
|
||||
add_dossier_intro: "Voeg iemand toe wiens gezondheidsgegevens je wilt beheren."
|
||||
add_dossier_intro: "Voeg iemand toe van wie je de gezondheidsdata wilt beheren."
|
||||
email_optional: "E-mail (optioneel)"
|
||||
email_optional_hint: "Als ze 18+ zijn, kunnen ze zelf inloggen"
|
||||
your_relation: "Jouw relatie met hen"
|
||||
select_relation: "Selecteer..."
|
||||
your_relation: "Jouw relatie tot deze persoon"
|
||||
select_relation: "Selecteer relatie..."
|
||||
i_provide_care: "Ik zorg voor deze persoon"
|
||||
|
||||
# Share access
|
||||
share_access_intro: "Nodig iemand uit voor toegang tot"
|
||||
their_relation: "Hun relatie met deze persoon"
|
||||
can_add_data: "Kan gegevens toevoegen (supplementen, notities, etc.)"
|
||||
their_relation: "Hun relatie tot deze persoon"
|
||||
can_add_data: "Kan data toevoegen"
|
||||
send_invitation: "Uitnodiging versturen"
|
||||
back_to_dossier: "Terug naar dossier"
|
||||
|
||||
|
|
@ -136,57 +169,85 @@ back_to_dossier: "Terug naar dossier"
|
|||
# Invitation email
|
||||
invite_email_subject: "%s heeft je toegevoegd aan inou"
|
||||
invite_email_body: "%s heeft je gezondheidsdossier toegevoegd aan inou zodat je je medische gegevens kunt bekijken en beheren."
|
||||
invite_email_cta: "Inloggen om te bekijken"
|
||||
invite_email_cta: "Log in om te bekijken"
|
||||
continue: "Doorgaan"
|
||||
i_am_their: "Ik ben hun..."
|
||||
|
||||
# Simple relation names (for display)
|
||||
my_role: "mijn rol"
|
||||
role: "role"
|
||||
role: "rol"
|
||||
section_privacy: "Privacy"
|
||||
people_with_access_count: "personen met toegang"
|
||||
view_audit_log: "Bekijk auditlog"
|
||||
export_data: "Download my data"
|
||||
people_with_access_count: "mensen met toegang"
|
||||
view_audit_log: "Activiteitenlog bekijken"
|
||||
export_data: "Mijn data downloaden"
|
||||
relation_with: "Relatie met"
|
||||
audit_log: "Auditlog"
|
||||
audit_log: "Activiteitenlog"
|
||||
audit_log_intro: "Activiteitengeschiedenis voor"
|
||||
audit_log_desc: "Bekijk wie dit dossier heeft bekeken of gewijzigd"
|
||||
install_title: "Verbind met Claude"
|
||||
install_intro: "Stel de inou-bridge in zodat Claude je gezondheidsgegevens kan analyseren"
|
||||
install_step1: "Stap 1: Download"
|
||||
audit_log_desc: "Bekijk wie dit dossier heeft geopend of gewijzigd"
|
||||
|
||||
# Permissions (RBAC)
|
||||
permissions_title: "Rechten"
|
||||
permissions_subtitle: "Bepaal wie toegang heeft tot dit dossier en wat ze kunnen doen"
|
||||
current_access: "Huidige toegang"
|
||||
grant_access: "Toegang verlenen"
|
||||
no_grantees: "Niemand anders heeft toegang tot dit dossier."
|
||||
person_email: "E-mailadres"
|
||||
person_email_hint: "Als ze nog geen account hebben, worden ze uitgenodigd er een aan te maken."
|
||||
person_name: "Naam"
|
||||
select_role: "Selecteer een rol..."
|
||||
custom_role: "Aangepaste rechten"
|
||||
permissions: "Rechten"
|
||||
op_read: "Lezen"
|
||||
op_write: "Schrijven"
|
||||
op_delete: "Verwijderen"
|
||||
op_manage: "Beheren"
|
||||
grant: "Toegang verlenen"
|
||||
revoke: "Intrekken"
|
||||
role_descriptions: "Rolbeschrijvingen"
|
||||
ops_legend: "Rechtenlegenda"
|
||||
op_read_desc: "Data bekijken"
|
||||
op_write_desc: "Data toevoegen/bewerken"
|
||||
op_delete_desc: "Data verwijderen"
|
||||
op_manage_desc: "Beheren wie toegang heeft"
|
||||
permissions_updated: "Rechten succesvol bijgewerkt."
|
||||
back: "Terug"
|
||||
can_add_data: "Kan data toevoegen"
|
||||
install_title: "Verbinden met Claude"
|
||||
install_intro: "Stel de inou bridge in zodat Claude je gezondheidsdata kan analyseren"
|
||||
install_step1: "Stap 1: Downloaden"
|
||||
install_step1_desc: "Download de bridge voor jouw platform"
|
||||
install_download_intro: "Download de inou-bridge voor jouw besturingssysteem:"
|
||||
install_step2: "Stap 2: Configureer"
|
||||
install_step2_desc: "Voeg toe aan Claude Desktop configuratie"
|
||||
install_config_intro: "Voeg dit toe aan je Claude Desktop configuratiebestand:"
|
||||
install_step3: "Stap 3: Test"
|
||||
install_download_intro: "Download de inou bridge voor jouw besturingssysteem:"
|
||||
install_step2: "Stap 2: Configureren"
|
||||
install_step2_desc: "Toevoegen aan Claude Desktop-configuratie"
|
||||
install_config_intro: "Voeg dit toe aan je Claude Desktop-configuratiebestand:"
|
||||
install_step3: "Stap 3: Testen"
|
||||
install_step3_desc: "Controleer de verbinding"
|
||||
install_test_intro: "Herstart Claude Desktop en vraag: 'Toon mijn inou profielen'"
|
||||
nav_install: "Verbind met Claude"
|
||||
nav_install: "Verbinden met Claude"
|
||||
nav_home: "Home"
|
||||
pending: "in afwachting"
|
||||
rate_limit_exceeded: "Te veel aanmeldpogingen vanaf uw locatie. Probeer het morgen opnieuw."
|
||||
section_genetics: Genetica
|
||||
no_genetics: Geen genetische gegevens
|
||||
rate_limit_exceeded: "Te veel aanmeldpogingen vanaf jouw locatie. Probeer het morgen opnieuw."
|
||||
section_genetics: "Genetica"
|
||||
no_genetics: "Geen genetische data"
|
||||
|
||||
sex_0: "onbekend"
|
||||
sex_1: "mannelijk"
|
||||
sex_2: "vrouwelijk"
|
||||
sex_1: "man"
|
||||
sex_2: "vrouw"
|
||||
sex_9: "anders"
|
||||
|
||||
# Friend invite email
|
||||
friend_invite_subject: "Kijk hier eens naar — %s"
|
||||
friend_invite_p1: "Ik gebruik <strong>inou</strong>, de veilige manier om gezondheidsgegevens op te slaan en te verkennen met AI. Het houdt alle gezondheidsinformatie van mijn familie op één plek — beeldvorming, labresultaten, medische dossiers — en ik dacht dat jij het misschien ook handig zou vinden."
|
||||
friend_invite_p2: "De echte kracht is dat je AI kunt gebruiken om alles te begrijpen: begrijpen wat een rapport echt betekent, trends in de tijd ontdekken, of gewoon vragen stellen in gewone taal en duidelijke antwoorden krijgen."
|
||||
friend_invite_p1: "Ik gebruik <strong>inou</strong>, de veilige manier om gezondheidsdata op te slaan en te verkennen met AI. Het houdt alle gezondheidsinformatie van mijn gezin op één plek — beeldvorming, labresultaten, medische dossiers — en ik dacht dat jij er ook iets aan zou kunnen hebben."
|
||||
friend_invite_p2: "De echte kracht zit in het gebruik van AI om er wijs uit te worden: begrijpen wat een rapport écht betekent, trends over tijd herkennen, of gewoon vragen stellen in normale taal en duidelijke antwoorden krijgen."
|
||||
friend_invite_btn: "Bekijk inou"
|
||||
friend_invite_dear: "Beste %s,"
|
||||
rel_0: "jij"
|
||||
rel_1: "Ouder"
|
||||
rel_2: "Kind"
|
||||
rel_3: "Partner"
|
||||
rel_4: "Broer/Zus"
|
||||
rel_4: "Broer/zus"
|
||||
rel_5: "Voogd"
|
||||
rel_6: "Verzorger"
|
||||
rel_6: "Mantelzorger"
|
||||
rel_7: "Coach"
|
||||
rel_8: "Arts"
|
||||
rel_9: "Vriend"
|
||||
|
|
@ -194,62 +255,62 @@ rel_10: "Anders"
|
|||
rel_98: "Anders"
|
||||
rel_99: "Demo"
|
||||
select_relation: "Selecteer relatie..."
|
||||
audit_dossier_added: "Nieuw dossier voor %s aangemaakt door %s"
|
||||
audit_dossier_added: "Een nieuw dossier voor %s aangemaakt door %s"
|
||||
audit_dossier_edited: "Dossier %s bewerkt door %s"
|
||||
audit_access_granted: "Toegang tot %s verleend aan %s"
|
||||
audit_dossier_created: Account aangemaakt door %s
|
||||
audit_access_revoked: Toegang voor %s tot %s ingetrokken
|
||||
audit_file_upload: Bestand %s geüpload door %s
|
||||
audit_file_delete: Bestand %s verwijderd door %s
|
||||
audit_file_category_change: Bestandscategorie %s gewijzigd door %s
|
||||
audit_genome_import: %s genetische varianten geïmporteerd
|
||||
audit_dossier_created: "Account aangemaakt door %s"
|
||||
audit_access_revoked: "Toegang van %s tot %s ingetrokken"
|
||||
audit_file_upload: "Bestand %s geüpload door %s"
|
||||
audit_file_delete: "Bestand %s verwijderd door %s"
|
||||
audit_file_category_change: "Categorie van bestand %s gewijzigd door %s"
|
||||
audit_genome_import: "%s genetische varianten geïmporteerd"
|
||||
|
||||
# Categorieën
|
||||
category000: Beeldvorming
|
||||
category001: Document
|
||||
category002: Labuitslag
|
||||
category003: Genoom
|
||||
category004: Upload
|
||||
category005: Consult
|
||||
category006: Diagnose
|
||||
category007: Beeldvormingsresultaat
|
||||
category008: EEG-resultaat
|
||||
category009: Vitale waarde
|
||||
category010: Beweging
|
||||
category011: Medicatie
|
||||
category012: Supplement
|
||||
category013: Voeding
|
||||
category014: Vruchtbaarheid
|
||||
category015: Symptoom
|
||||
category016: Notitie
|
||||
category017: Medische geschiedenis
|
||||
category018: Familiegeschiedenis
|
||||
category019: Operatie
|
||||
category020: Ziekenhuisopname
|
||||
category021: Geboortegegevens
|
||||
category022: Medisch hulpmiddel
|
||||
category023: Therapie
|
||||
category024: Beoordeling
|
||||
category025: Zorgverlener
|
||||
category026: Vraag
|
||||
# Categories (category000 = imaging, etc.)
|
||||
category000: "Beeldvorming"
|
||||
category001: "Document"
|
||||
category002: "Labresultaat"
|
||||
category003: "Genoom"
|
||||
category004: "Upload"
|
||||
category005: "Consult"
|
||||
category006: "Diagnose"
|
||||
category007: "Beeldvormingsbevinding"
|
||||
category008: "EEG-bevinding"
|
||||
category009: "Vitale waarde"
|
||||
category010: "Beweging"
|
||||
category011: "Medicatie"
|
||||
category012: "Supplement"
|
||||
category013: "Voeding"
|
||||
category014: "Vruchtbaarheid"
|
||||
category015: "Symptoom"
|
||||
category016: "Notitie"
|
||||
category017: "Medische geschiedenis"
|
||||
category018: "Familiegeschiedenis"
|
||||
category019: "Operatie"
|
||||
category020: "Ziekenhuisopname"
|
||||
category021: "Geboorteakte"
|
||||
category022: "Medisch hulpmiddel"
|
||||
category023: "Therapie"
|
||||
category024: "Beoordeling"
|
||||
category025: "Zorgverlener"
|
||||
category026: "Vraag"
|
||||
|
||||
# Genome
|
||||
genome_english_only: "Alle genetische informatie is in het Engels. Gebruik Claude om het in het Nederlands te bespreken."
|
||||
genome_english_only: ""
|
||||
genome_variants: "varianten"
|
||||
genome_hidden: "verborgen"
|
||||
genome_show_all_categories: "Toon alle %d categorieën"
|
||||
|
||||
# API
|
||||
api_token: "API Token"
|
||||
api_token_use: "[EN] Use this token to authenticate API requests:"
|
||||
api_token_warning: "[EN] Keep this private. Anyone with this token can access your health data."
|
||||
api_token_none: "[EN] Generate a token to access the API programmatically or connect AI assistants."
|
||||
api_token_generate: "Generate Token"
|
||||
api_token_regenerate: "Regenerate Token"
|
||||
api_token_regenerate_confirm: "[EN] This will invalidate your current token. Any connected apps will need to be updated."
|
||||
api_authentication: "Authentication"
|
||||
api_auth_instructions: "[EN] Include your API token in the Authorization header:"
|
||||
copy: "Copy"
|
||||
api_token: "API-token"
|
||||
api_token_use: "Gebruik dit token om API-verzoeken te authenticeren:"
|
||||
api_token_warning: "Houd dit privé. Iedereen met dit token heeft toegang tot je gezondheidsdata."
|
||||
api_token_none: "Genereer een token om programmatisch toegang te krijgen tot de API of AI-assistenten te verbinden."
|
||||
api_token_generate: "Token genereren"
|
||||
api_token_regenerate: "Token opnieuw genereren"
|
||||
api_token_regenerate_confirm: "Dit maakt je huidige token ongeldig. Verbonden apps moeten worden bijgewerkt."
|
||||
api_authentication: "Authenticatie"
|
||||
api_auth_instructions: "Voeg je API-token toe in de Authorization-header:"
|
||||
copy: "Kopiëren"
|
||||
relation: "Relatie"
|
||||
relation_to: "Aan"
|
||||
me: "Ik"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Norsk
|
||||
|
||||
# Landing
|
||||
headline_1: "Dine helsedata."
|
||||
headline_2: "Din AI."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Português
|
||||
|
||||
# Landing
|
||||
headline_1: "Seus dados de saúde."
|
||||
headline_2: "Sua IA."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Русский
|
||||
|
||||
# Landing
|
||||
headline_1: "Ваши медицинские данные."
|
||||
headline_2: "Ваш ИИ."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: Svenska
|
||||
|
||||
# Landing
|
||||
headline_1: "Din hälsodata."
|
||||
headline_2: "Din AI."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,316 @@
|
|||
language_name: Türkçe
|
||||
|
||||
# Landing
|
||||
headline_1: Sağlık verilerin.
|
||||
headline_2: "AI'ın."
|
||||
headline_3: Cevapların.
|
||||
intro: "Görüntüleme, laboratuvarlar ve daha fazlasını yükle. Ne baktığını anlamana yardımcı olması için AI'ını bağla."
|
||||
email: E-posta
|
||||
get_started: Başla
|
||||
data_yours: Verilerin senin
|
||||
never_training: Asla eğitim için kullanılmadı
|
||||
never_training_desc: Görüntülerin asla AI modellerini eğitmek için kullanılmaz.
|
||||
never_shared: Asla paylaşılmadı
|
||||
never_shared_desc: Verilerini asla kimseyle paylaşmayız.
|
||||
encrypted: Askeri düzey şifreleme
|
||||
encrypted_desc: Hem durağan halde hem aktarımda. Verilerin asla korumasız seyahat etmez.
|
||||
delete: İstediğin zaman sil
|
||||
delete_desc: Verilerin, senin kontrolün.
|
||||
|
||||
# Verify
|
||||
check_email: E-postanı kontrol et
|
||||
code_sent_to: "6 haneli kodu gönderdik:"
|
||||
verification_code: Doğrulama kodu
|
||||
verify: Doğrula
|
||||
use_different_email: Farklı bir e-posta kullan
|
||||
invalid_code: Geçersiz veya süresi dolmuş kod. Lütfen tekrar dene.
|
||||
|
||||
# Onboard
|
||||
create_dossier: Dosyanı oluştur
|
||||
create_profile_intro: Başlamak için kendin hakkında bilgi ver.
|
||||
name: İsim
|
||||
name_placeholder: İsmin
|
||||
date_of_birth: Doğum tarihi
|
||||
sex_at_birth: Doğumdaki cinsiyet
|
||||
female: Kadın
|
||||
male: Erkek
|
||||
create_my_dossier: Dosyamı oluştur
|
||||
|
||||
# Minor error
|
||||
must_be_18: Hesap oluşturmak için 18 yaşında olmalısın
|
||||
minor_explanation: Başkası için bunu kuruyorsan, önce kendi profilinle başla. Bu, yalnızca senin onların sağlık verilerine erişebildiğinden emin olur.
|
||||
minor_next_steps: Dosyanı oluşturduktan sonra başkalarını ekleyebilirsin.
|
||||
use_different_dob: Farklı bir doğum tarihi kullan
|
||||
|
||||
# Minor login block
|
||||
minor_login_blocked: Giriş yapmak için 18 yaşında olmalısın
|
||||
minor_ask_guardian: "Dosyana erişmek için %s'e sor."
|
||||
minor_ask_guardian_generic: Dosyana erişmek için bir ebeveyne veya veliye sor.
|
||||
|
||||
# Dashboard
|
||||
dossiers: Dosyalar
|
||||
dossiers_intro: Kendin veya başkaları için sağlık verilerini yönet
|
||||
you: sen
|
||||
view: Görüntüle
|
||||
save: Kaydet
|
||||
cancel: İptal
|
||||
add_dossier: Dosya ekle
|
||||
edit_dossier: Dosyayı düzenle
|
||||
care: bakım
|
||||
logout: Çıkış yap
|
||||
|
||||
# Profile detail
|
||||
back_to_dossiers: Dosyalara geri dön
|
||||
born: Doğumlu
|
||||
no_access_yet: Sadece sen erişebilirsin.
|
||||
people_with_access: Erişimi olanlar
|
||||
share_access: Erişimi paylaş
|
||||
manage_permissions: İzinleri yönet
|
||||
can_edit: veri ekleyebilir
|
||||
remove: Kaldır
|
||||
confirm_revoke: "Erişimi kaldır?"
|
||||
|
||||
# Dossier sections
|
||||
section_imaging: Görüntüleme
|
||||
section_labs: Laboratuvarlar
|
||||
section_uploads: Yüklemeler
|
||||
section_vitals: Vitals
|
||||
section_medications: İlaçlar
|
||||
section_records: Kayıtlar
|
||||
section_journal: Günlük
|
||||
section_checkin: Günlük Kontrol
|
||||
section_procedures: Prosedürler
|
||||
section_assessments: "Assessments"
|
||||
section_genetics: Genetik
|
||||
section_supplements: Takviyeler
|
||||
section_symptoms: Belirtiler
|
||||
section_hospitalizations: Hastaneye Yatışlar
|
||||
section_therapies: Terapiler
|
||||
section_consultations: Konsültasyonlar
|
||||
section_diagnoses: Tanılar
|
||||
section_exercise: Egzersiz
|
||||
section_nutrition: Beslenme
|
||||
section_fertility: Doğurganlık
|
||||
section_notes: Notlar
|
||||
section_history: Tıbbi Geçmiş
|
||||
section_family_history: Aile Öyküsü
|
||||
section_birth: Doğum
|
||||
section_devices: Cihazlar
|
||||
section_providers: Sağlık Sağlayıcıları
|
||||
section_questions: Sorular
|
||||
section_privacy: Gizlilik
|
||||
|
||||
# Daily Check-in
|
||||
checkin_summary: Vitals, ilaçlar, belirtiler takip et
|
||||
checkin_build_profile: Takip etmek istediğin şeyleri ekle
|
||||
btn_vitals: Vitals
|
||||
btn_medications: İlaçlar
|
||||
btn_supplements: Takviyeler
|
||||
btn_exercise: Egzersiz
|
||||
|
||||
# Plural forms (use %d for count)
|
||||
slice_one: "%d dilim"
|
||||
slice_other: "%d dilim"
|
||||
series_one: "%d seri"
|
||||
series_other: "%d seri"
|
||||
order_one: "%d sipariş"
|
||||
order_other: "%d sipariş"
|
||||
result_one: "%d sonuç"
|
||||
result_other: "%d sonuç"
|
||||
|
||||
# Section summaries
|
||||
imaging_summary: "%d çalışma · %d dilim"
|
||||
no_imaging: Görüntüleme verisi yok
|
||||
no_lab_data: Laboratuvar verisi yok
|
||||
no_files: Dosya yok
|
||||
no_upload_access: Yükleme iznin yok
|
||||
files_summary: "%d dosya (%s)"
|
||||
series_count: "%d seriler"
|
||||
vitals_desc: Tansiyon, kalp atışı, SpO₂, kilo, glukoz
|
||||
medications_desc: Reçeteler ve takviyeler
|
||||
records_desc: Klinik notlar ve tıbbi kayıtlar
|
||||
journal_desc: Belirtiler, ağrı ve gözlemler
|
||||
|
||||
# Buttons and actions
|
||||
open: Aç
|
||||
open_viewer: Görüntüleyiciyi aç
|
||||
manage: Yönet
|
||||
show_all_studies: "Tüm %d çalışmaları göster..."
|
||||
coming_soon: Çok yakında
|
||||
|
||||
# Upload page
|
||||
upload_files: Sağlık verileri yükle
|
||||
upload_files_intro: Tıbbi görüntüleme, laboratuvar sonuçları, genom dosyaları veya sağlıkla ilgili herhangi bir belge yükle.
|
||||
upload_hint_broad: DICOM, PDF, CSV, VCF ve daha fazlası
|
||||
uploading: Yükleniyor...
|
||||
files_uploaded: dosya yüklendi
|
||||
upload_scans: Taramaları yükle
|
||||
upload_scans_intro: Görüntüleme çalışmanızdan DICOM dosyaları içeren bir klasör yükleyin.
|
||||
upload_drop: Bir klasörü buraya tıkla veya sürükle
|
||||
upload_hint: Sadece DICOM klasörleri
|
||||
|
||||
# Add profile
|
||||
add_dossier_intro: Sağlık verilerini yönetmek istediğiniz birini ekleyin.
|
||||
email_optional: E-posta (isteğe bağlı)
|
||||
email_optional_hint: 18 yaşındalarsa, kendileri giriş yapabilir
|
||||
your_relation: Onlarla ilişkin
|
||||
select_relation: İlişki seç...
|
||||
i_provide_care: Bu kişiye bakım sağlıyorum
|
||||
|
||||
# Share access
|
||||
share_access_intro: Erişim için birini davet et
|
||||
their_relation: Bu kişiyle ilişkileri
|
||||
can_add_data: Veri ekleyebilir
|
||||
send_invitation: Davet gönder
|
||||
back_to_dossier: Dosyaya geri dön
|
||||
|
||||
# Relations
|
||||
|
||||
# Invitation email
|
||||
invite_email_subject: "%s seni inou'ya ekledi"
|
||||
invite_email_body: "%s sağlık dosyanı inou'ya ekledi, böylece tıbbi verilerini görüntüleyebilir ve yönetebilirsin."
|
||||
invite_email_cta: Görüntülemek için giriş yap
|
||||
continue: Devam et
|
||||
i_am_their: Ben onun...
|
||||
|
||||
# Simple relation names (for display)
|
||||
my_role: rolüm
|
||||
role: rol
|
||||
section_privacy: Gizlilik
|
||||
people_with_access_count: kişi erişimli
|
||||
view_audit_log: Denetim günlüğünü görüntüle
|
||||
export_data: Verilerimi indir
|
||||
relation_with: İlişki
|
||||
audit_log: Denetim günlüğü
|
||||
audit_log_intro: "Etkinlik geçmişi:"
|
||||
audit_log_desc: Bu dosyaya kimlerin eriştiğini veya değişiklik yaptığını takip edin
|
||||
|
||||
# Permissions (RBAC)
|
||||
permissions_title: İzinler
|
||||
permissions_subtitle: Bu dosyaya kimlerin erişebileceğini ve ne yapabileceklerini kontrol et
|
||||
current_access: Mevcut erişim
|
||||
grant_access: Erişim ver
|
||||
no_grantees: Başka kimsenin bu dosyaya erişimi yok.
|
||||
person_email: E-posta adresi
|
||||
person_email_hint: Hesapları yoksa, oluşturmaya davet edilecekler.
|
||||
person_name: İsim
|
||||
select_role: Rol seç...
|
||||
custom_role: Özel izinler
|
||||
permissions: İzinler
|
||||
op_read: Oku
|
||||
op_write: Yaz
|
||||
op_delete: Sil
|
||||
op_manage: Yönet
|
||||
grant: Erişim ver
|
||||
revoke: İptal et
|
||||
role_descriptions: Rol açıklamaları
|
||||
ops_legend: İzin açıklamaları
|
||||
op_read_desc: Verileri görüntüle
|
||||
op_write_desc: Veri ekle/düzenle
|
||||
op_delete_desc: Verileri kaldır
|
||||
op_manage_desc: Kimin erişimi olduğunu yönet
|
||||
permissions_updated: İzinler başarıyla güncellendi.
|
||||
back: Geri
|
||||
can_add_data: Veri ekleyebilir
|
||||
install_title: "Claude'a Bağlan"
|
||||
install_intro: "Claude'un sağlık verilerini analiz etmesi için inou bridge'i kur"
|
||||
install_step1: "Adım 1: İndir"
|
||||
install_step1_desc: "Platformun için bridge'i al"
|
||||
install_download_intro: "İşletim sistemin için inou bridge'i indir:"
|
||||
install_step2: "Adım 2: Yapılandır"
|
||||
install_step2_desc: "Claude Desktop config'e ekle"
|
||||
install_config_intro: "Claude Desktop yapılandırma dosyana bunu ekle:"
|
||||
install_step3: "Adım 3: Test"
|
||||
install_step3_desc: Bağlantıyı doğrula
|
||||
install_test_intro: "Claude Desktop'u yeniden başlat ve sor: 'inou profillerimi göster'"
|
||||
nav_install: "Claude'a Bağlan"
|
||||
nav_home: Ana Sayfa
|
||||
pending: beklemede
|
||||
rate_limit_exceeded: Konumundan çok fazla kayıt denemesi. Lütfen yarın tekrar dene.
|
||||
section_genetics: Genetik
|
||||
no_genetics: Genetik veri yok
|
||||
|
||||
sex_0: bilinmiyor
|
||||
sex_1: erkek
|
||||
sex_2: kadın
|
||||
sex_9: diğer
|
||||
|
||||
# Friend invite email
|
||||
friend_invite_subject: "Bunu dene — %s"
|
||||
friend_invite_p1: "<strong>inou</strong>'yu kullanıyorum, sağlık verilerini güvenli bir şekilde depolamak ve AI ile keşfetmek için. Tüm ailemin sağlık bilgilerini tek bir yerde tutuyorum — görüntüleme çalışmaları, laboratuvar sonuçları, tıbbi kayıtlar — ve sana da faydalı olabileceğini düşündüm."
|
||||
friend_invite_p2: "Gerçek güç, hepsini anlamlandırmak için AI kullanabilmek: bir raporun ne anlama geldiğini anlamak, zaman içinde eğilimleri tespit etmek veya sadece sade bir dilde sorular sormak ve net yanıtlar almak."
|
||||
friend_invite_btn: "inou'yu dene"
|
||||
friend_invite_dear: "Sevgili %s,"
|
||||
rel_0: sen
|
||||
rel_1: Ebeveyn
|
||||
rel_2: Çocuk
|
||||
rel_3: Eş
|
||||
rel_4: Kardeş
|
||||
rel_5: Veli
|
||||
rel_6: Bakıcı
|
||||
rel_7: Koç
|
||||
rel_8: Doktor
|
||||
rel_9: Arkadaş
|
||||
rel_10: Diğer
|
||||
rel_98: Diğer
|
||||
rel_99: Demo
|
||||
select_relation: İlişki seç...
|
||||
audit_dossier_added: "%s için %s tarafından yeni dosya oluşturuldu"
|
||||
audit_dossier_edited: "%s dosyası %s tarafından düzenlendi"
|
||||
audit_access_granted: "%s için %s erişimi verildi"
|
||||
audit_dossier_created: "%s tarafından hesap oluşturuldu"
|
||||
audit_access_revoked: "%s için %s erişimi iptal edildi"
|
||||
audit_file_upload: "%s dosyası %s tarafından yüklendi"
|
||||
audit_file_delete: "%s dosyası %s tarafından silindi"
|
||||
audit_file_category_change: "%s dosyasının kategorisi %s tarafından değiştirildi"
|
||||
audit_genome_import: "%s genetik varyant içe aktarıldı"
|
||||
|
||||
# Categories (category000 = imaging, etc.)
|
||||
category000: Görüntüleme
|
||||
category001: Belge
|
||||
category002: Laboratuvar sonucu
|
||||
category003: Genom
|
||||
category004: Yükleme
|
||||
category005: Konsültasyon
|
||||
category006: Tanı
|
||||
category007: Görüntüleme bulgusu
|
||||
category008: EEG bulgusu
|
||||
category009: Vital bulgu
|
||||
category010: Egzersiz
|
||||
category011: İlaç
|
||||
category012: Takviye
|
||||
category013: Beslenme
|
||||
category014: Doğurganlık
|
||||
category015: Belirti
|
||||
category016: Not
|
||||
category017: Tıbbi geçmiş
|
||||
category018: Aile öyküsü
|
||||
category019: Ameliyat
|
||||
category020: Hastaneye yatış
|
||||
category021: Doğum kaydı
|
||||
category022: Tıbbi cihaz
|
||||
category023: Terapi
|
||||
category024: Değerlendirme
|
||||
category025: Sağlık sağlayıcı
|
||||
category026: Soru
|
||||
|
||||
# Genome
|
||||
genome_english_only: ""
|
||||
genome_variants: varyant
|
||||
genome_hidden: gizli
|
||||
genome_show_all_categories: "Tüm %d kategoriyi göster"
|
||||
|
||||
# API
|
||||
api_token: API Token
|
||||
api_token_use: "API isteklerini kimlik doğrulamak için bu token'i kullanın:"
|
||||
api_token_warning: "Bu özel tutun. Bu token'e sahip olan herkes sağlık verilerinize erişebilir."
|
||||
api_token_none: "API'ye programatik olarak erişmek veya AI asistanları bağlamak için bir token oluşturun."
|
||||
api_token_generate: Token Oluştur
|
||||
api_token_regenerate: "Token'i Yeniden Oluştur"
|
||||
api_token_regenerate_confirm: Bu, mevcut tokeninizi geçersiz kılacaktır. Bağlı tüm uygulamalar güncellenmelidir.
|
||||
api_authentication: Kimlik doğrulama
|
||||
api_auth_instructions: "API tokeninizi Authorization header'a ekleyin:"
|
||||
copy: Kopyala
|
||||
relation: İlişki
|
||||
relation_to: İlişki
|
||||
me: Ben
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
language_name: 中文
|
||||
|
||||
# Landing
|
||||
headline_1: "你的健康数据。"
|
||||
headline_2: "你的AI。"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
|
|
@ -144,7 +145,6 @@ type PageData struct {
|
|||
HasLabs, HasGenome, Embed bool
|
||||
StudyCount, LabCount, TotalSlices int
|
||||
AuditList []AuditViewEntry
|
||||
SelfStats DossierStats
|
||||
APIToken string
|
||||
TempToken string
|
||||
TempTokenExpires string
|
||||
|
|
@ -164,6 +164,16 @@ type PageData struct {
|
|||
Languages []LangOption
|
||||
RelationTargets []RelationTarget
|
||||
RelationTo string
|
||||
// OAuth consent
|
||||
ClientName string
|
||||
ClientID string
|
||||
RedirectURI string
|
||||
ResponseType string
|
||||
State string
|
||||
CodeChallenge string
|
||||
CodeChallengeMethod string
|
||||
UserName string
|
||||
Content template.HTML
|
||||
}
|
||||
|
||||
type CategoryAccess struct {
|
||||
|
|
@ -194,12 +204,6 @@ func initDB() {
|
|||
}
|
||||
|
||||
// Native names for languages (used in language selector dropdowns).
|
||||
var langNativeNames = map[string]string{
|
||||
"da": "Dansk", "de": "Deutsch", "en": "English", "es": "Español",
|
||||
"fi": "Suomi", "fr": "Français", "it": "Italiano", "ja": "日本語",
|
||||
"ko": "한국어", "nl": "Nederlands", "no": "Norsk", "pt": "Português",
|
||||
"ru": "Русский", "sv": "Svenska", "zh": "中文",
|
||||
}
|
||||
|
||||
func loadTranslations() {
|
||||
translations = make(map[string]map[string]string)
|
||||
|
|
@ -218,25 +222,29 @@ func loadTranslations() {
|
|||
}
|
||||
file.Close()
|
||||
}
|
||||
// Build sorted language options from loaded translations
|
||||
codes := make([]string, 0, len(translations))
|
||||
for code := range translations { codes = append(codes, code) }
|
||||
sort.Strings(codes)
|
||||
langOptions = make([]LangOption, 0, len(codes))
|
||||
for _, code := range codes {
|
||||
name := langNativeNames[code]
|
||||
if name == "" { name = code }
|
||||
flag := ""
|
||||
// Reuse the same flag mapping as langFlag template func
|
||||
// Build language options from lang_* keys in en.yaml, sorted by native name
|
||||
en := translations["en"]
|
||||
langOptions = nil
|
||||
for k, name := range en {
|
||||
if !strings.HasPrefix(k, "lang_") { continue }
|
||||
code := strings.TrimPrefix(k, "lang_")
|
||||
langOptions = append(langOptions, LangOption{Code: code, Name: name})
|
||||
}
|
||||
sort.Slice(langOptions, func(i, j int) bool { return langOptions[i].Name < langOptions[j].Name })
|
||||
// Add flags
|
||||
for i := range langOptions {
|
||||
code := langOptions[i].Code
|
||||
flags := map[string]string{
|
||||
"en": "\U0001F1EC\U0001F1E7", "nl": "\U0001F1F3\U0001F1F1", "de": "\U0001F1E9\U0001F1EA",
|
||||
"ru": "\U0001F1F7\U0001F1FA", "zh": "\U0001F1E8\U0001F1F3", "ja": "\U0001F1EF\U0001F1F5",
|
||||
"ko": "\U0001F1F0\U0001F1F7", "fr": "\U0001F1EB\U0001F1F7", "es": "\U0001F1EA\U0001F1F8",
|
||||
"pt": "\U0001F1E7\U0001F1F7", "it": "\U0001F1EE\U0001F1F9", "sv": "\U0001F1F8\U0001F1EA",
|
||||
"no": "\U0001F1F3\U0001F1F4", "da": "\U0001F1E9\U0001F1F0", "fi": "\U0001F1EB\U0001F1EE",
|
||||
"tr": "\U0001F1F9\U0001F1F7", "vi": "\U0001F1FB\U0001F1F3", "id": "\U0001F1EE\U0001F1E9",
|
||||
"hi": "\U0001F1EE\U0001F1F3", "th": "\U0001F1F9\U0001F1ED", "pl": "\U0001F1F5\U0001F1F1",
|
||||
"uk": "\U0001F1FA\U0001F1E6",
|
||||
}
|
||||
if f, ok := flags[code]; ok { flag = f }
|
||||
langOptions = append(langOptions, LangOption{Code: code, Name: name, Flag: flag})
|
||||
if f, ok := flags[code]; ok { langOptions[i].Flag = f }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -588,6 +596,23 @@ func render(w http.ResponseWriter, r *http.Request, data PageData) {
|
|||
data.T = translations[data.Lang]
|
||||
if data.T == nil { data.T = translations["en"] }
|
||||
data.RequestPath = r.URL.Path
|
||||
if data.Languages == nil { data.Languages = langOptions }
|
||||
// Pre-render page content — use localized template if available
|
||||
page := data.Page
|
||||
if data.Lang != "en" {
|
||||
if templates.Lookup(data.Page + "_" + data.Lang) != nil {
|
||||
page = data.Page + "_" + data.Lang
|
||||
}
|
||||
}
|
||||
if t := templates.Lookup(page); t != nil {
|
||||
var buf bytes.Buffer
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Page template %q error: %v\n", data.Page, err)
|
||||
http.Error(w, "Template error", 500)
|
||||
return
|
||||
}
|
||||
data.Content = template.HTML(buf.String())
|
||||
}
|
||||
if err := templates.ExecuteTemplate(w, "base.tmpl", data); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Template error: %v\n", err)
|
||||
http.Error(w, "Template error", 500)
|
||||
|
|
@ -599,9 +624,7 @@ func handleLanding(w http.ResponseWriter, r *http.Request) {
|
|||
if r.URL.Path != "/" { http.NotFound(w, r); return }
|
||||
p := getLoggedInDossier(r)
|
||||
lang := getLang(r)
|
||||
pageName := "landing"
|
||||
switch lang { case "nl", "ru", "de", "fr", "es", "pt", "it", "sv", "no", "da", "fi", "ja", "ko", "zh": pageName = "landing_" + lang }
|
||||
render(w, r, PageData{Page: pageName, Lang: lang, Dossier: p})
|
||||
render(w, r, PageData{Page: "landing", Lang: lang, Dossier: p})
|
||||
}
|
||||
|
||||
func getClientIP(r *http.Request) string {
|
||||
|
|
@ -770,6 +793,11 @@ func handlePrivacy(w http.ResponseWriter, r *http.Request) {
|
|||
render(w, r, PageData{Page: "privacy", Lang: getLang(r), Dossier: p})
|
||||
}
|
||||
|
||||
func handleDocs(w http.ResponseWriter, r *http.Request) {
|
||||
p := getLoggedInDossier(r)
|
||||
render(w, r, PageData{Page: "docs", Lang: getLang(r), Dossier: p})
|
||||
}
|
||||
|
||||
func handlePricing(w http.ResponseWriter, r *http.Request) {
|
||||
p := getLoggedInDossier(r)
|
||||
render(w, r, PageData{Page: "pricing", Lang: getLang(r), Dossier: p})
|
||||
|
|
@ -965,7 +993,7 @@ func getDossierStats(dossierID string) DossierStats {
|
|||
if cj == 0 { cj = 1 }
|
||||
return ci > cj
|
||||
})
|
||||
if len(all) > 5 {
|
||||
if len(all) > 6 {
|
||||
stats.OverflowCount = len(all) - 5
|
||||
all = all[:5]
|
||||
}
|
||||
|
|
@ -979,8 +1007,6 @@ func handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|||
if p.Name == "" { http.Redirect(w, r, "/onboard", http.StatusSeeOther); return }
|
||||
lang := getLang(r)
|
||||
|
||||
selfStats := getDossierStats(p.DossierID)
|
||||
|
||||
// All cat-0 entries I can access (self + granted) — RBAC checked
|
||||
allDossiers, _ := lib.EntryRead(p.DossierID, "", &lib.Filter{Category: 0})
|
||||
// Access grants for relation/ops metadata
|
||||
|
|
@ -988,8 +1014,14 @@ func handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|||
grantMap := map[string]*lib.Access{}
|
||||
for _, g := range grants { grantMap[g.DossierID] = g }
|
||||
|
||||
// Build accessible dossier list with names index
|
||||
// Build accessible dossier list — self first, then others
|
||||
nameMap := map[string]string{} // dossierID → name
|
||||
self := AccessEntry{
|
||||
DossierID: p.DossierID, Name: p.Name, DateOfBirth: p.DateOfBirth,
|
||||
Sex: p.Sex, Lang: p.Preferences.Language,
|
||||
Relation: T(lang, "you"), CanEdit: true, IsSelf: true,
|
||||
Stats: getDossierStats(p.DossierID),
|
||||
}
|
||||
var accessible []AccessEntry
|
||||
for _, entry := range allDossiers {
|
||||
if entry.DossierID == p.DossierID { continue }
|
||||
|
|
@ -1098,7 +1130,8 @@ func handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|||
prevTier, prevGroup = t, g
|
||||
}
|
||||
|
||||
render(w, r, PageData{Page: "dashboard", Lang: lang, Embed: isEmbed(r), Dossier: p, AccessibleDossiers: accessible, SelfStats: selfStats})
|
||||
accessible = append([]AccessEntry{self}, accessible...)
|
||||
render(w, r, PageData{Page: "dashboard", Lang: lang, Embed: isEmbed(r), Dossier: p, AccessibleDossiers: accessible})
|
||||
}
|
||||
|
||||
func handleDemo(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -2151,6 +2184,7 @@ func setupMux() http.Handler {
|
|||
mux.HandleFunc("/invite", handleInvite)
|
||||
mux.HandleFunc("/privacy-policy", handlePrivacy)
|
||||
mux.HandleFunc("/privacy-policy/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/privacy-policy", http.StatusMovedPermanently) })
|
||||
mux.HandleFunc("/docs", handleDocs)
|
||||
mux.HandleFunc("/pricing", handlePricing)
|
||||
mux.HandleFunc("/faq", handleFAQ)
|
||||
mux.HandleFunc("/security", handleSecurity)
|
||||
|
|
|
|||
|
|
@ -52,68 +52,16 @@
|
|||
<div class="lang-menu">
|
||||
<span class="lang-current" style="text-transform: uppercase;">{{.Lang}}</span>
|
||||
<div class="lang-dropdown">
|
||||
<a href="#" onclick="setLang('en')"{{if eq .Lang "en"}} class="active"{{end}}>English</a>
|
||||
<a href="#" onclick="setLang('nl')"{{if eq .Lang "nl"}} class="active"{{end}}>Nederlands</a>
|
||||
<a href="#" onclick="setLang('de')"{{if eq .Lang "de"}} class="active"{{end}}>Deutsch</a>
|
||||
<a href="#" onclick="setLang('fr')"{{if eq .Lang "fr"}} class="active"{{end}}>Français</a>
|
||||
<a href="#" onclick="setLang('es')"{{if eq .Lang "es"}} class="active"{{end}}>Español</a>
|
||||
<a href="#" onclick="setLang('pt')"{{if eq .Lang "pt"}} class="active"{{end}}>Português</a>
|
||||
<a href="#" onclick="setLang('it')"{{if eq .Lang "it"}} class="active"{{end}}>Italiano</a>
|
||||
<a href="#" onclick="setLang('ru')"{{if eq .Lang "ru"}} class="active"{{end}}>Русский</a>
|
||||
<a href="#" onclick="setLang('sv')"{{if eq .Lang "sv"}} class="active"{{end}}>Svenska</a>
|
||||
<a href="#" onclick="setLang('no')"{{if eq .Lang "no"}} class="active"{{end}}>Norsk</a>
|
||||
<a href="#" onclick="setLang('da')"{{if eq .Lang "da"}} class="active"{{end}}>Dansk</a>
|
||||
<a href="#" onclick="setLang('fi')"{{if eq .Lang "fi"}} class="active"{{end}}>Suomi</a>
|
||||
<a href="#" onclick="setLang('ja')"{{if eq .Lang "ja"}} class="active"{{end}}>日本語</a>
|
||||
<a href="#" onclick="setLang('ko')"{{if eq .Lang "ko"}} class="active"{{end}}>한국어</a>
|
||||
<a href="#" onclick="setLang('zh')"{{if eq .Lang "zh"}} class="active"{{end}}>中文</a>
|
||||
{{range .Languages}}{{if eq $.Lang .Code}}<a href="#" onclick="setLang('{{.Code}}')" class="active">{{.Name}}</a>
|
||||
{{end}}{{end}}{{range .Languages}}{{if ne $.Lang .Code}}<a href="#" onclick="setLang('{{.Code}}')">{{.Name}}</a>
|
||||
{{end}}{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
{{if eq .Page "landing"}}{{template "landing" .}}
|
||||
{{else if eq .Page "landing_nl"}}{{template "landing_nl" .}}
|
||||
{{else if eq .Page "landing_ru"}}{{template "landing_ru" .}}
|
||||
{{else if eq .Page "landing_de"}}{{template "landing_de" .}}
|
||||
{{else if eq .Page "landing_fr"}}{{template "landing_fr" .}}
|
||||
{{else if eq .Page "landing_es"}}{{template "landing_es" .}}
|
||||
{{else if eq .Page "landing_pt"}}{{template "landing_pt" .}}
|
||||
{{else if eq .Page "landing_it"}}{{template "landing_it" .}}
|
||||
{{else if eq .Page "landing_sv"}}{{template "landing_sv" .}}
|
||||
{{else if eq .Page "landing_no"}}{{template "landing_no" .}}
|
||||
{{else if eq .Page "landing_da"}}{{template "landing_da" .}}
|
||||
{{else if eq .Page "landing_fi"}}{{template "landing_fi" .}}
|
||||
{{else if eq .Page "landing_ja"}}{{template "landing_ja" .}}
|
||||
{{else if eq .Page "landing_ko"}}{{template "landing_ko" .}}
|
||||
{{else if eq .Page "landing_zh"}}{{template "landing_zh" .}}
|
||||
{{else if eq .Page "verify"}}{{template "verify" .}}
|
||||
{{else if eq .Page "onboard"}}{{template "onboard" .}}
|
||||
{{else if eq .Page "minor_error"}}{{template "minor_error" .}}
|
||||
{{else if eq .Page "dashboard"}}{{template "dashboard" .}}
|
||||
{{else if eq .Page "dossier"}}{{template "dossier" .}}
|
||||
{{else if eq .Page "add_dossier"}}{{template "add_dossier" .}}
|
||||
{{else if eq .Page "share"}}{{template "share" .}}
|
||||
{{else if eq .Page "upload"}}{{template "upload" .}}
|
||||
{{else if eq .Page "audit"}}{{template "audit" .}}
|
||||
{{else if eq .Page "connect"}}{{template "connect" .}}
|
||||
{{else if eq .Page "connect_nl"}}{{template "connect_nl" .}}
|
||||
{{else if eq .Page "connect_ru"}}{{template "connect_ru" .}}
|
||||
{{else if eq .Page "invite"}}{{template "invite" .}}
|
||||
{{else if eq .Page "login"}}{{template "login" .}}
|
||||
{{else if eq .Page "privacy"}}{{template "privacy" .}}
|
||||
{{else if eq .Page "security"}}{{template "security" .}}
|
||||
{{else if eq .Page "dpa"}}{{template "dpa" .}}
|
||||
{{else if eq .Page "terms"}}{{template "terms" .}}
|
||||
{{else if eq .Page "styleguide"}}{{template "styleguide" .}}
|
||||
{{else if eq .Page "pricing"}}{{template "pricing" .}}
|
||||
{{else if eq .Page "faq"}}{{template "faq" .}}
|
||||
{{else if eq .Page "trackers"}}{{template "trackers" .}}
|
||||
{{else if eq .Page "permissions"}}{{template "permissions" .}}
|
||||
{{else if eq .Page "edit_access"}}{{template "edit_access" .}}
|
||||
{{else if eq .Page "edit_rbac"}}{{template "edit_rbac" .}}
|
||||
{{end}}
|
||||
{{.Content}}
|
||||
|
||||
<script>
|
||||
function setLang(lang) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,249 @@
|
|||
{{define "dpa_de"}}
|
||||
<style>
|
||||
.dpa-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.dpa-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.dpa-card h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.dpa-card .intro {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.dpa-card h2 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-top: 0;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.dpa-card h3 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-top: 24px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.dpa-card h3:first-child { margin-top: 0; }
|
||||
|
||||
.dpa-card p {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.dpa-card p:last-child { margin-bottom: 0; }
|
||||
|
||||
.dpa-card strong {
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.dpa-card a {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.inou-brand {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.dpa-card ul {
|
||||
margin: 0 0 16px 0;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.dpa-card li {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.dpa-container { padding: 24px 16px 48px; }
|
||||
.dpa-card { padding: 32px 24px; }
|
||||
.dpa-card h1 { font-size: 2rem; }
|
||||
.dpa-card .intro { font-size: 1.05rem; }
|
||||
.dpa-card h2 { font-size: 1.25rem; }
|
||||
.dpa-card h3 { font-size: 1rem; }
|
||||
.dpa-card p { font-size: 0.95rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.dpa-container { padding: 16px 12px 32px; }
|
||||
.dpa-card { padding: 24px 16px; }
|
||||
.dpa-card h1 { font-size: 1.75rem; }
|
||||
.dpa-card .intro { font-size: 1rem; }
|
||||
.dpa-card h2 { font-size: 1.15rem; }
|
||||
.dpa-card p { font-size: 0.9rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="dpa-container">
|
||||
|
||||
<div class="dpa-card">
|
||||
<h1>Vertrag zur Datenverarbeitung</h1>
|
||||
<p class="intro">Dieser Vertrag beschreibt, wie <span class="inou-brand">inou</span> deine Gesundheitsdaten verarbeitet. Er gilt für alle Nutzer*innen und alle Drittanbieter-Dienste, die über unsere Plattform auf deine Daten zugreifen.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Definitionen</h2>
|
||||
|
||||
<h3>Datenverantwortlicher.</h3>
|
||||
<p>Du. Du entscheidest, welche Daten du hochlädst, wer darauf zugreifen darf und wann du sie löschen lässt.</p>
|
||||
|
||||
<h3>Datenverarbeiter.</h3>
|
||||
<p><span class="inou-brand">inou</span>. Wir speichern, verschlüsseln und übertragen deine Daten gemäß deinen Anweisungen.</p>
|
||||
|
||||
<h3>Drittanbieter-Dienste.</h3>
|
||||
<p>Du kannst externe Dienste mit deinem Konto verbinden, z. B. KI‑Assistenten. Diese Dienste agieren als unabhängige Verantwortliche oder als direkt von dir beauftragte Verarbeiter – nicht als unsere Subverarbeiter. Wir beauftragen keine Subverarbeiter für Speicherung oder Kernfunktionalität.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Verarbeitete Daten</h2>
|
||||
|
||||
<h3>Gesundheitsdaten.</h3>
|
||||
<p>Medizinische Bildgebung (DICOM‑Dateien einschließlich MRI, CT, Röntgen), Laborergebnisse, genetische/genomische Daten und alle anderen Gesundheitsinformationen, die du hochlädst. Genetische und genomische Daten stellen besondere Kategorien von Daten gemäß Art. 9 der GDPR dar und werden ausschließlich auf Grundlage deiner ausdrücklichen Zustimmung verarbeitet.</p>
|
||||
|
||||
<h3>Kontodaten.</h3>
|
||||
<p>Name, E‑Mail-Adresse, Geburtsdatum und Geschlecht. Werden für die Kontoverwaltung und den medizinischen Kontext verwendet.</p>
|
||||
|
||||
<h3>Technische Daten.</h3>
|
||||
<p>IP‑Adressen und Sitzungs‑IDs. Werden ausschließlich für Sicherheit und Zugriffskontrolle verwendet.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Wie wir sie verarbeiten</h2>
|
||||
|
||||
<h3>Speicherung.</h3>
|
||||
<p>Alle Gesundheitsdaten werden mit FIPS 140‑3 validierter Kryptografie verschlüsselt, bevor sie gespeichert werden. Die Daten liegen auf dedizierter Infrastruktur in den Vereinigten Staaten, die wir besitzen und betreiben.</p>
|
||||
|
||||
<h3>Übertragung.</h3>
|
||||
<p>Alle Daten im Transit sind durch TLS 1.3 verschlüsselt. Wenn du Drittanbieter‑Dienste verbindest, reisen die Daten über eine verschlüsselte Brücke direkt zu deiner Sitzung.</p>
|
||||
|
||||
<h3>Zugriff.</h3>
|
||||
<p>Nur du und von dir explizit autorisierte Konten können auf deine Daten zugreifen. Der Zugriff von Mitarbeitern erfordert deine ausdrückliche Anfrage, ist auf leitende Personen beschränkt und wird protokolliert.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Verarbeitungsbeschränkungen</h2>
|
||||
|
||||
<p>Wir verarbeiten deine Daten ausschließlich zur Bereitstellung des Dienstes. Insbesondere tun wir nicht:</p>
|
||||
<ul>
|
||||
<li>Deine Daten für das Training von KI‑Modellen verwenden</li>
|
||||
<li>Deine Daten an Dritte verkaufen, vermieten oder teilen</li>
|
||||
<li>Deine Daten für Werbung oder Profiling analysieren</li>
|
||||
<li>Auf deine Daten ohne deine ausdrückliche Anfrage zugreifen</li>
|
||||
<li>Deine Daten nach Löschung des Kontos aufbewahren</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Drittanbieter‑Verbindungen</h2>
|
||||
|
||||
<p>Wenn du einen KI‑Assistenten oder einen anderen Dienst mit <span class="inou-brand">inou</span> verbindest:</p>
|
||||
<ul>
|
||||
<li>Du autorisierst jede Verbindung explizit</li>
|
||||
<li>Daten werden nur für deine aktive Sitzung übertragen</li>
|
||||
<li>Wir speichern keine Kopien der übertragenen Daten</li>
|
||||
<li>Du kannst den Zugriff jederzeit widerrufen</li>
|
||||
<li>Jeder Drittanbieter arbeitet nach seiner eigenen Datenschutzerklärung</li>
|
||||
</ul>
|
||||
<p>Wir empfehlen, die Datenschutzerklärung jedes Dienstes, den du verbindest, zu prüfen.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Sicherheitsmaßnahmen</h2>
|
||||
|
||||
<h3>Verschlüsselung.</h3>
|
||||
<p>FIPS 140‑3 validierte Verschlüsselung im Ruhezustand. TLS 1.3 Verschlüsselung in der Übertragung. Anwendungsschicht‑Verschlüsselung vor der Datenbankspeicherung.</p>
|
||||
|
||||
<h3>Infrastruktur.</h3>
|
||||
<p>Dedizierte Hardware. Keine geteilten Cloud‑Umgebungen. Redundante Speicherung mit RAID‑Z2. Unterbrechungsfreie Stromversorgung mit Generator‑Backup.</p>
|
||||
|
||||
<h3>Zugriffskontrolle.</h3>
|
||||
<p>Rollenbasierte Zugriffskontrolle. Pflichtauthentifizierung. Alle Zugriffe werden protokolliert und auditierbar.</p>
|
||||
|
||||
<h3>Überwachung.</h3>
|
||||
<p>Kontinuierliche automatisierte Überwachung. Eindringungserkennung. Regelmäßige Sicherheitsbewertungen.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Datenspeicherung</h2>
|
||||
|
||||
<p>Wir behalten deine Daten so lange auf, wie dein Konto aktiv ist. Wenn du dein Konto löschst:</p>
|
||||
<ul>
|
||||
<li>Alle personenbezogenen Daten werden dauerhaft gelöscht</li>
|
||||
<li>Alle Gesundheitsdaten werden dauerhaft gelöscht</li>
|
||||
<li>Löschung erfolgt sofort und unwiderruflich</li>
|
||||
<li>Backups werden innerhalb von 30 Tagen überschrieben</li>
|
||||
</ul>
|
||||
<p>Wir bieten keine Wiederherstellung gelöschter Daten an.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Deine Rechte</h2>
|
||||
|
||||
<h3>Zugriff.</h3>
|
||||
<p>Sieh dir alles an und exportiere alles, was wir speichern – die von dir eingegebenen Daten, Kontodetails, Zugriffsprotokolle und Audit‑Historie.</p>
|
||||
|
||||
<h3>Berichtigung.</h3>
|
||||
<p>Korrigiere ungenaue Daten direkt oder auf Anfrage.</p>
|
||||
|
||||
<h3>Löschung.</h3>
|
||||
<p>Lösche dein Konto und alle zugehörigen Daten sofort.</p>
|
||||
|
||||
<h3>Portabilität.</h3>
|
||||
<p>Lade die von dir eingegebenen Daten in Standardformaten herunter. Deine hochgeladenen Dateien gehören bereits dir.</p>
|
||||
|
||||
<h3>Widerspruch.</h3>
|
||||
<p>Widerrufe jede Erlaubnis jederzeit. Wir reagieren sofort.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Compliance</h2>
|
||||
|
||||
<p>Dieser Vertrag wurde entwickelt, um die folgenden Vorschriften einzuhalten:</p>
|
||||
<ul>
|
||||
<li><strong>GDPR</strong> (Datenschutz‑Grundverordnung der Europäischen Union)</li>
|
||||
<li><strong>FADP</strong> (Schweizerisches Bundesgesetz über den Datenschutz)</li>
|
||||
<li><strong>HIPAA</strong> (US Health Insurance Portability and Accountability Act)</li>
|
||||
</ul>
|
||||
<p>Wir wenden den höchsten Standard unabhängig von deiner Gerichtsbarkeit an.</p>
|
||||
</div>
|
||||
|
||||
<div class="dpa-card">
|
||||
<h2>Kontakt</h2>
|
||||
<p>Datenschutzbeauftragter: <a href="mailto:privacy@inou.com">privacy@inou.com</a></p>
|
||||
<p>Fragen zur Datenverarbeitung: <a href="mailto:privacy@inou.com">privacy@inou.com</a></p>
|
||||
<p>Dieses Dokument wurde zuletzt am 8. Februar 2026 aktualisiert.</p>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,121 +1,519 @@
|
|||
{{define "landing_de"}}
|
||||
<style>
|
||||
.landing-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 48px; width: 100%; margin-left: auto; margin-right: auto; margin-bottom: 24px; }
|
||||
.hero-answer { text-align: center; font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin-top: 16px; margin-bottom: 32px; }
|
||||
.hero-answer .inou { font-weight: 700; color: var(--accent); }
|
||||
.hero-tagline { text-align: center; font-size: 1.3rem; font-weight: 600; color: var(--text); margin-bottom: 32px; }
|
||||
|
||||
.landing-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 48px;
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* Carousel */
|
||||
.carousel {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.carousel-track {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
.carousel-slide {
|
||||
min-width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.carousel-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.carousel-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--border);
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.carousel-dot.active {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
/* Hero - Block 1 */
|
||||
.hero-sources {
|
||||
|
||||
font-size: 1.1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.9;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.hero-sources span { display: block; }
|
||||
.hero-sources .different {
|
||||
|
||||
|
||||
}
|
||||
|
||||
.hero-pivot {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
|
||||
}
|
||||
.hero-pivot span { display: block; }
|
||||
.hero-pivot .emphasis {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.hero-answer {
|
||||
text-align: center;
|
||||
font-size: 1.7rem;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
line-height: 1.5;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.hero-answer .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.hero-tagline {
|
||||
text-align: center;
|
||||
font-size: 2.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.carousel-caption {
|
||||
text-align: center;
|
||||
font-size: 0.95rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
min-height: 3em;
|
||||
padding: 0 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hero-cta { margin-bottom: 0; text-align: center; }
|
||||
.hero-cta .btn { padding: 18px 56px; font-size: 0.9rem; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; border-radius: 4px; }
|
||||
.story-prose.warm { font-size: 1.1rem; line-height: 1.8; color: var(--text); }
|
||||
.story-prose.warm p { margin-bottom: 20px; }
|
||||
.story-prose.warm .emphasis { font-weight: 600; font-size: 1.15rem; }
|
||||
.story-title { font-size: 1.25rem; font-weight: 600; color: var(--text); margin-bottom: 32px; }
|
||||
.story-pair { margin-bottom: 32px; }
|
||||
.story-pair .data { font-size: 1.1rem; font-weight: 400; color: var(--text); margin-bottom: 4px; }
|
||||
.story-pair .reality { font-size: 1rem; font-weight: 300; font-style: italic; color: var(--text-muted); }
|
||||
.story-transition { font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin: 32px 0; padding: 24px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
|
||||
.story-gaps { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 32px; }
|
||||
.hero-cta .btn {
|
||||
padding: 18px 56px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Story - Block 2 */
|
||||
.story-prose.warm {
|
||||
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: var(--text);
|
||||
}
|
||||
.story-prose.warm p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.story-prose.warm .emphasis {
|
||||
font-weight: 600;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.story-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.story-pair {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-pair .data {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.story-pair .reality {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.story-transition {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin: 32px 0;
|
||||
padding: 24px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.story-gaps {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-gaps span { display: block; }
|
||||
.story-gaps .indent { font-style: italic; }
|
||||
.story-connections { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 32px; }
|
||||
|
||||
.story-connections {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-connections span { display: block; }
|
||||
.story-ai { font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin-bottom: 32px; }
|
||||
|
||||
.story-ai {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-ai span { display: block; }
|
||||
.story-ai .last { font-style: italic; }
|
||||
.story-prose { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 20px; }
|
||||
.story-ai .last {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.story-prose {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.story-prose:last-of-type { margin-bottom: 32px; }
|
||||
.story-prose strong { font-weight: 600; color: var(--text); }
|
||||
.story-prose .inou { font-weight: 700; color: var(--accent); }
|
||||
.story-closing { font-size: 1.25rem; font-weight: 400; color: var(--text); padding-top: 24px; border-top: 1px solid var(--border); }
|
||||
.story-closing .inou { font-weight: 700; color: var(--accent); }
|
||||
.trust-card { width: 100%; margin-left: auto; margin-right: auto; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 32px 48px; margin-bottom: 24px; }
|
||||
.trust-card .section-label { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 24px; }
|
||||
.trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }
|
||||
.trust-item { font-size: 0.9rem; font-weight: 300; color: var(--text-muted); line-height: 1.6; }
|
||||
.trust-item strong { display: block; font-weight: 600; color: var(--text); margin-bottom: 4px; }
|
||||
.landing-footer { padding: 16px 0; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
|
||||
.landing-footer-left { font-size: 0.9rem; color: var(--text-muted); display: flex; gap: 16px; align-items: center; }
|
||||
.landing-footer-left a { color: var(--text-muted); text-decoration: none; }
|
||||
|
||||
.story-closing {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.story-closing .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* Trust section */
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 32px 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.trust-card .section-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.trust-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 32px;
|
||||
}
|
||||
.trust-item {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.trust-item strong {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.landing-footer {
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.landing-footer-left {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
.landing-footer-left a {
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
}
|
||||
.landing-footer-left a:hover { color: var(--accent); }
|
||||
.landing-footer-right { font-size: 1rem; }
|
||||
.landing-footer-right .inou { font-weight: 700; color: var(--accent); }
|
||||
.landing-footer-right .health { font-weight: 400; color: var(--text-muted); }
|
||||
@media (max-width: 768px) { .trust-card { padding: 24px; } .trust-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; } }
|
||||
@media (max-width: 480px) { .trust-card { padding: 20px 16px; } .trust-grid { grid-template-columns: 1fr; gap: 20px; } .landing-footer { flex-direction: column; gap: 12px; text-align: center; } .landing-footer-left { flex-direction: column; gap: 8px; } }
|
||||
.landing-footer-right .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
.landing-footer-right .health {
|
||||
font-weight: 400;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto; padding: 24px; }
|
||||
.hero-sources {
|
||||
font-size: 1rem; line-height: 1.8; margin-bottom: 32px; }
|
||||
.hero-pivot { font-size: 1.1rem; margin-bottom: 32px;
|
||||
}
|
||||
.hero-pivot .emphasis { font-size: 1.3rem; }
|
||||
.hero-answer {
|
||||
text-align: center; font-size: 1.2rem; margin-top: 16px;
|
||||
margin-bottom: 8px; }
|
||||
.hero-tagline { font-size: 2rem; margin-bottom: 8px; }
|
||||
.carousel-caption { font-size: 0.85rem; }
|
||||
.hero-cta .btn { padding: 14px 40px; }
|
||||
.story-pair .data { font-size: 1rem; }
|
||||
.story-pair .reality { font-size: 0.95rem; }
|
||||
.trust-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto; padding: 20px 16px; }
|
||||
.hero-sources {
|
||||
font-size: 0.95rem; line-height: 1.9; }
|
||||
.hero-pivot { font-size: 1rem; }
|
||||
.hero-pivot .emphasis { font-size: 1.2rem; }
|
||||
.story-pair { margin-bottom: 24px; }
|
||||
.trust-grid { grid-template-columns: 1fr; gap: 20px; }
|
||||
.landing-footer { flex-direction: column; gap: 12px; text-align: center; }
|
||||
.landing-footer-left { flex-direction: column; gap: 8px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sg-container">
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="hero">
|
||||
<div class="hero-answer"><span class="inou">inou</span> organisiert und teilt Ihre Gesundheitsakte mit Ihrer KI — sicher und privat.</div>
|
||||
<div class="hero-tagline">Ihre Gesundheit, verstanden.</div>
|
||||
<div class="hero-cta">{{if .Dossier}}<a href="/invite" class="btn btn-primary">Freund einladen</a>{{else}}<a href="/start" class="btn btn-primary">Anmelden</a>{{end}}{{if .Error}}<div class="error" style="margin-top: 24px;">{{.Error}}</div>{{end}}</div>
|
||||
<div class="hero-tagline">Deine Gesundheit, verstanden.</div>
|
||||
<div class="hero-answer">Alle deine Gesundheitsdaten — organisiert, privat und bereit für deine KI.</div>
|
||||
<div class="carousel">
|
||||
<div class="carousel-track">
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-1.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-2.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-3.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-4.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-5.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-6.webp')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-caption" id="carousel-caption">Verfolge deine Labortrends im Zeitverlauf — sieh genau, was deine KI sieht, wenn sie eine Änderung meldet.</div>
|
||||
<div class="carousel-dots">
|
||||
<button class="carousel-dot active" data-index="0"></button>
|
||||
<button class="carousel-dot" data-index="1"></button>
|
||||
<button class="carousel-dot" data-index="2"></button>
|
||||
<button class="carousel-dot" data-index="3"></button>
|
||||
<button class="carousel-dot" data-index="4"></button>
|
||||
<button class="carousel-dot" data-index="5"></button>
|
||||
</div>
|
||||
<div class="hero-cta">
|
||||
{{if .Dossier}}<a href="/invite" class="btn btn-primary">Einen Freund einladen</a>{{else}}<a href="/start" class="btn btn-primary">Einloggen</a>{{end}}
|
||||
{{if .Error}}<div class="error" style="margin-top: 24px;">{{.Error}}</div>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">Sie brauchen KI für Ihre Gesundheit</h2>
|
||||
<h2 class="story-title">Du brauchst KI für deine Gesundheit</h2>
|
||||
|
||||
<div class="story-prose warm">
|
||||
<p>Ihre Gesundheitsdaten sind über Dutzende von Orten verstreut — bei Ihrem Kardiologen, Ihrem Neurologen, im Labor, in Ihrer Smartwatch, Ihren Apps, Ihrem 23andMe. Und nur Sie kennen den Rest: was Sie essen, was Sie trinken, welche Nahrungsergänzungsmittel Sie nehmen. Ihr Trainingsplan. Ihre Symptome. Ihre Ziele — ob Sie schwanger werden möchten, für einen Marathon trainieren oder einfach weniger müde sein wollen.</p>
|
||||
<p>Ob Sie gesund sind und es bleiben wollen, mit einer schwierigen Diagnose kämpfen oder sich um ein Familienmitglied kümmern, das sich nicht selbst vertreten kann — kein einzelner Arzt sieht das vollständige Bild. Kein System verbindet alles.</p>
|
||||
<p>Aber Sie haben Zugang zu allem. Ihnen fehlt nur die Expertise, um alles zu verstehen.</p>
|
||||
<p class="emphasis">Ihre KI hat sie. inou gibt ihr das vollständige Bild.</p>
|
||||
<p>Deine Gesundheitsdaten leben an einem Dutzend verschiedenen Orten — bei deinem Kardiologen, deinem Neurologen, deinem Labor, deiner Uhr, deinen Apps, deinem 23andMe. Und nur du kennst den Rest: was du isst, was du trinkst, welche Nahrungsergänzungsmittel du einnimmst. Deine Trainingsroutine. Deine Symptome. Deine Ziele — ob du versuchst schwanger zu werden, dich auf einen Marathon vorzubereiten oder einfach nur weniger erschöpft zu fühlen.</p>
|
||||
|
||||
<p>Ob du gesund bist und so bleiben willst, eine schwierige Diagnose durchläufst oder dich um ein Familienmitglied kümmerst, das sich nicht selbst vertreten kann — kein einziger Arzt sieht das komplette Bild. Kein System verbindet es.</p>
|
||||
|
||||
<p>Aber <strong><em>du</em></strong> hast Zugriff auf alles. Du hast einfach nicht die Expertise, um alles zu verstehen.</p>
|
||||
|
||||
<p class="emphasis">Deine KI macht es. inou gibt dir das komplette Bild.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">Die Herausforderung</h2>
|
||||
<div class="story-pair"><div class="data">Ihr MRT hat 4.000 Schichten.</div><div class="reality">Es wurde in 10 Minuten ausgewertet.</div></div>
|
||||
<div class="story-pair"><div class="data">Ihr Genom hat Millionen von Varianten.</div><div class="reality">Sie haben nur Ihre Augenfarbe und Ihre Herkunft erfahren.</div></div>
|
||||
<div class="story-pair"><div class="data">Ihr Blutbild hat Dutzende von Markern.</div><div class="reality">Ihr Arzt sagte "alles sieht gut aus."</div></div>
|
||||
<div class="story-pair"><div class="data">Ihre Uhr hat 10.000 Stunden Schlaf aufgezeichnet.</div><div class="reality">Ihr Trainer weiß nicht, dass sie existiert.</div></div>
|
||||
<div class="story-pair"><div class="data">Sie haben hundert verschiedene Nahrungsergänzungsmittel ausprobiert.</div><div class="reality">Niemand hat gefragt, welche.</div></div>
|
||||
<div class="story-transition">Die Verbindungen sind da.<br>Sie sind nur zu komplex für eine einzelne Person.</div>
|
||||
<div class="story-pair">
|
||||
<div class="data">Deine MRT hat 4.000 Schichten.</div>
|
||||
<div class="reality">Es wurde in 10 Minuten gelesen.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Dein Genom hat Millionen von Varianten.</div>
|
||||
<div class="reality">Alles, was du gelernt hast, war deine Augenfarbe und wo deine Vorfahren herkommen.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Deine Blutuntersuchung hat Dutzende von Markern.</div>
|
||||
<div class="reality">Dein Arzt sagte: 'Alles sieht gut aus.'</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Deine Uhr hat 10.000 Stunden Schlaf aufgezeichnet.</div>
|
||||
<div class="reality">Dein Trainer weiß nicht, dass es existiert.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Du hast einhundert verschiedene Nahrungsergänzungsmittel ausprobiert.</div>
|
||||
<div class="reality">Niemand hat gefragt, welche.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-transition">
|
||||
Die Verbindungen sind da.<br>
|
||||
Sie sind einfach zu komplex, damit eine Person sie erfassen kann.
|
||||
</div>
|
||||
|
||||
<div class="story-gaps">
|
||||
<span>Niemand weiß, wie Ihr Körper Warfarin verarbeitet — nicht einmal Sie.</span>
|
||||
<span class="indent">Aber die Antwort könnte bereits in Ihrem 23andMe versteckt sein.</span>
|
||||
<span>Dieses "unauffällig" in Ihrem MRT — hat jemand wirklich alle 4.000 Schichten genau angesehen?</span>
|
||||
<span>Ihre Schilddrüse ist "im Normbereich" — aber niemand hat sie mit Ihrer Müdigkeit, Ihrem Gewicht, dass Ihnen immer kalt ist, verbunden.</span>
|
||||
<span>Niemand weiß, wie dein Körper Warfarin verarbeitet — nicht einmal du.</span>
|
||||
<span class="indent">Aber die Antwort könnte bereits in deinem 23andMe versteckt sein.</span>
|
||||
<span>Das 'unauffällige' auf deiner MRT — hat jemand alle 4.000 Schichten genau betrachtet?</span>
|
||||
<span>Deine Schilddrüse ist 'im Bereich' — aber niemand hat es mit deiner Müdigkeit, deinem Gewicht, ständigem Kältegefühl verbunden.</span>
|
||||
</div>
|
||||
|
||||
<div class="story-connections">
|
||||
<span>Niemand verbindet Ihren Nachmittagskaffee mit Ihrer Schlafqualität.</span>
|
||||
<span>Ihren Eisenspiegel mit Ihrer Trainingsmüdigkeit.</span>
|
||||
<span>Ihre Genetik mit Ihrem Gehirnnebel.</span>
|
||||
<span>Niemand verbindet deinen Nachmittagscafé mit deinen Schlafwerten.</span>
|
||||
<span>Deine Eisenwerte mit deiner Trainingsmüdigkeit.</span>
|
||||
<span>Deine Genetik mit deinem Gehirnnebel.</span>
|
||||
</div>
|
||||
|
||||
<div class="story-ai">
|
||||
<span>Ihre KI vergisst nicht.</span>
|
||||
<span>Hetzt nicht.</span>
|
||||
<span>Findet, was übersehen wurde.</span>
|
||||
<span class="last">Spezialisiert sich nicht — sieht Sie als Ganzes.</span>
|
||||
<span>Deine KI vergisst nicht.</span>
|
||||
<span>Eilt nicht.</span>
|
||||
<span>Findet, was verpasst wurde.</span>
|
||||
<span class="last">Spezialisiert sich nicht — sieht das komplette du.</span>
|
||||
</div>
|
||||
<div class="story-closing"><span class="inou">inou</span> lässt Ihre KI alles berücksichtigen — jede Schicht, jeden Marker, jede Variante — verbindet alles und gibt Ihnen endlich Antworten, die niemand sonst geben konnte.</div>
|
||||
|
||||
<div class="story-closing"><span class="inou">inou</span> lässt deine KI alles berücksichtigen — jede Schicht, jeden Marker, jede Variante — verbindet alles und gibt dir endlich Antworten, die sonst niemand geben könnte.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">Warum wir das gebaut haben</h2>
|
||||
<p class="story-prose">Sie haben jahrelang Gesundheitsdaten gesammelt. Scans aus dem Krankenhaus. Blutwerte aus dem Labor. Ergebnisse aus dem Patientenportal. Daten von Ihrer Uhr. Vielleicht sogar Ihre DNA.</p>
|
||||
<p class="story-prose">Und dann gibt es alles, was nur Sie wissen — Ihr Gewicht, Ihr Blutdruck, Ihr Trainingsplan, die Nahrungsergänzungsmittel, die Sie nehmen, die Symptome, die Sie immer vergessen zu erwähnen.</p>
|
||||
<p class="story-prose">Es ist alles da — aber verstreut über Systeme, die nicht miteinander kommunizieren, bei Spezialisten, die nur ihren Teil sehen, oder in Ihrem eigenen Kopf eingeschlossen.</p>
|
||||
<p class="story-prose">Ihr Kardiologe weiß nicht, was Ihr Neurologe gefunden hat. Ihr Trainer hat Ihre Blutwerte nicht gesehen. Ihr Arzt hat keine Ahnung, welche Nahrungsergänzungsmittel Sie nehmen. Und keiner von ihnen hat Zeit, sich mit Ihnen hinzusetzen und die Punkte zu verbinden.</p>
|
||||
<p class="story-prose"><strong>KI kann das endlich.</strong> Sie kann zusammenführen, was kein einzelner Experte sieht — und es Ihnen auch noch erklären.</p>
|
||||
<p class="story-prose">Aber diese Daten passen nicht in ein Chat-Fenster. Und das Letzte, was Sie wollen, ist Ihre Krankengeschichte auf fremden Servern, die deren Modelle trainiert.</p>
|
||||
<p class="story-prose"><span class="inou">inou</span> bringt alles zusammen — Labor, Bildgebung, Genetik, Vitalwerte, Medikamente, Nahrungsergänzungsmittel — verschlüsselt, privat und mit niemandem geteilt. Ihre KI verbindet sich sicher. Ihre Daten bleiben Ihre.</p>
|
||||
<div class="story-closing">Ihre Gesundheit, verstanden.</div>
|
||||
|
||||
<p class="story-prose">Du hast Jahre an Gesundheitsdaten gesammelt. Scans aus dem Krankenhaus. Blutuntersuchungen aus dem Labor. Ergebnisse aus dem Portal deines Arztes. Daten von deiner Uhr. Vielleicht sogar dein DNA.</p>
|
||||
|
||||
<p class="story-prose">Und dann gibt es alles, was nur du kennst — dein Gewicht, dein Blutdruck, dein Trainingsplan, die Nahrungsergänzungsmittel, die du einnimmst, die Symptome, die du erwähnen wolltest.</p>
|
||||
|
||||
<p class="story-prose">Alles ist da — aber verteilt über Systeme, die nicht miteinander kommunizieren, von Spezialisten gehalten, die nur ihr Stück sehen, oder in deinem eigenen Kopf verankert.</p>
|
||||
|
||||
<p class="story-prose">Dein Kardiologe weiß nicht, was dein Neurologe gefunden hat. Dein Trainer hat deine Blutuntersuchung nicht gesehen. Dein Arzt hat keine Ahnung, welche Nahrungsergänzungsmittel du einnimmst. Und keiner von ihnen hat Zeit, mit dir zu sitzen und die Punkte zu verbinden.</p>
|
||||
|
||||
<p class="story-prose"><strong>KI kann endlich.</strong> Sie kann zusammenziehen, was kein einziger Experte sieht — und es dir tatsächlich erklären.</p>
|
||||
|
||||
<p class="story-prose">Aber diese Daten passen nicht in ein Chatfenster. Und das Letzte, was du willst, ist deine medizinische Vorgeschichte auf fremden Servern, die ihre Modelle trainieren.</p>
|
||||
|
||||
<p class="story-prose"><span class="inou">inou</span> bringt alles zusammen — Labore, Bildgebung, Genetik, Vitalwerte, Medikamente, Nahrungsergänzungsmittel — verschlüsselt, privat und mit absolut niemandem geteilt. Deine KI verbindet sich sicher. Deine Daten bleiben deine.</p>
|
||||
|
||||
<div class="story-closing">Deine Gesundheit, verstanden.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="trust-card">
|
||||
<div class="section-label">{{.T.data_yours}}</div>
|
||||
<div class="trust-grid">
|
||||
<div class="trust-item"><strong>{{.T.never_training}}</strong>{{.T.never_training_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.never_shared}}</strong>{{.T.never_shared_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.encrypted}}</strong>{{.T.encrypted_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.delete}}</strong>{{.T.delete_desc}}</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.never_training}}</strong>
|
||||
{{.T.never_training_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.never_shared}}</strong>
|
||||
{{.T.never_shared_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.encrypted}}</strong>
|
||||
{{.T.encrypted_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.delete}}</strong>
|
||||
{{.T.delete_desc}}
|
||||
</div>
|
||||
</div>
|
||||
<footer class="landing-footer">
|
||||
<div class="landing-footer-left"><span>© 2025</span><a href="/privacy-policy">Datenschutz</a></div>
|
||||
<span class="landing-footer-right"><span class="inou">inou</span> <span class="health">health</span></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var track = document.querySelector('.carousel-track');
|
||||
var dots = document.querySelectorAll('.carousel-dot');
|
||||
var caption = document.getElementById('carousel-caption');
|
||||
var captions = [
|
||||
'Verfolge deine Labortrends im Zeitverlauf \u2014 sieh genau, was deine KI sieht, wenn sie eine Änderung meldet.',
|
||||
'Deine Labore, Scans und dein Genom an einem Ort \u2014 durchsuche alles, auf das deine KI Zugriff hat.',
|
||||
'Betrachte deine eigene MRT \u2014 zoome in die gleichen Schichten, die deine KI analysiert hat.',
|
||||
'Deine Gehirnscans in 3D \u2014 navigiere durch jede Ebene, verifiziere jede Entdeckung, die deine KI gemacht hat.',
|
||||
'Deine KI verbindet die Punkte über Labore und Genom \u2014 und erklärt es in einfacher Sprache.',
|
||||
'Deine Röntgenaufnahme, volle Auflösung \u2014 zoome in die Befunde, die deine KI markiert hat.'
|
||||
];
|
||||
var count = dots.length;
|
||||
var current = 0;
|
||||
function go(i) {
|
||||
current = i;
|
||||
track.style.transform = 'translateX(-' + (i * 100) + '%)';
|
||||
dots.forEach(function(d, j) { d.classList.toggle('active', j === i); });
|
||||
caption.textContent = captions[i];
|
||||
}
|
||||
dots.forEach(function(d) {
|
||||
d.addEventListener('click', function() { go(+d.dataset.index); });
|
||||
});
|
||||
setInterval(function() { go((current + 1) % count); }, 8000);
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
|
@ -1,121 +1,519 @@
|
|||
{{define "landing_es"}}
|
||||
<style>
|
||||
.landing-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 48px; width: 100%; margin-left: auto; margin-right: auto; margin-bottom: 24px; }
|
||||
.hero-answer { text-align: center; font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin-top: 16px; margin-bottom: 32px; }
|
||||
.hero-answer .inou { font-weight: 700; color: var(--accent); }
|
||||
.hero-tagline { text-align: center; font-size: 1.3rem; font-weight: 600; color: var(--text); margin-bottom: 32px; }
|
||||
|
||||
.landing-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 48px;
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* Carousel */
|
||||
.carousel {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.carousel-track {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
.carousel-slide {
|
||||
min-width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.carousel-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.carousel-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--border);
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.carousel-dot.active {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
/* Hero - Block 1 */
|
||||
.hero-sources {
|
||||
|
||||
font-size: 1.1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.9;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.hero-sources span { display: block; }
|
||||
.hero-sources .different {
|
||||
|
||||
|
||||
}
|
||||
|
||||
.hero-pivot {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
|
||||
}
|
||||
.hero-pivot span { display: block; }
|
||||
.hero-pivot .emphasis {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.hero-answer {
|
||||
text-align: center;
|
||||
font-size: 1.7rem;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
line-height: 1.5;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.hero-answer .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.hero-tagline {
|
||||
text-align: center;
|
||||
font-size: 2.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.carousel-caption {
|
||||
text-align: center;
|
||||
font-size: 0.95rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
min-height: 3em;
|
||||
padding: 0 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hero-cta { margin-bottom: 0; text-align: center; }
|
||||
.hero-cta .btn { padding: 18px 56px; font-size: 0.9rem; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; border-radius: 4px; }
|
||||
.story-prose.warm { font-size: 1.1rem; line-height: 1.8; color: var(--text); }
|
||||
.story-prose.warm p { margin-bottom: 20px; }
|
||||
.story-prose.warm .emphasis { font-weight: 600; font-size: 1.15rem; }
|
||||
.story-title { font-size: 1.25rem; font-weight: 600; color: var(--text); margin-bottom: 32px; }
|
||||
.story-pair { margin-bottom: 32px; }
|
||||
.story-pair .data { font-size: 1.1rem; font-weight: 400; color: var(--text); margin-bottom: 4px; }
|
||||
.story-pair .reality { font-size: 1rem; font-weight: 300; font-style: italic; color: var(--text-muted); }
|
||||
.story-transition { font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin: 32px 0; padding: 24px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
|
||||
.story-gaps { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 32px; }
|
||||
.hero-cta .btn {
|
||||
padding: 18px 56px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Story - Block 2 */
|
||||
.story-prose.warm {
|
||||
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: var(--text);
|
||||
}
|
||||
.story-prose.warm p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.story-prose.warm .emphasis {
|
||||
font-weight: 600;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.story-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.story-pair {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-pair .data {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.story-pair .reality {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.story-transition {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin: 32px 0;
|
||||
padding: 24px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.story-gaps {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-gaps span { display: block; }
|
||||
.story-gaps .indent { font-style: italic; }
|
||||
.story-connections { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 32px; }
|
||||
|
||||
.story-connections {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-connections span { display: block; }
|
||||
.story-ai { font-size: 1.25rem; font-weight: 400; color: var(--text); line-height: 1.8; margin-bottom: 32px; }
|
||||
|
||||
.story-ai {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.story-ai span { display: block; }
|
||||
.story-ai .last { font-style: italic; }
|
||||
.story-prose { font-size: 1rem; font-weight: 300; color: var(--text-muted); line-height: 1.8; margin-bottom: 20px; }
|
||||
.story-ai .last {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.story-prose {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.story-prose:last-of-type { margin-bottom: 32px; }
|
||||
.story-prose strong { font-weight: 600; color: var(--text); }
|
||||
.story-prose .inou { font-weight: 700; color: var(--accent); }
|
||||
.story-closing { font-size: 1.25rem; font-weight: 400; color: var(--text); padding-top: 24px; border-top: 1px solid var(--border); }
|
||||
.story-closing .inou { font-weight: 700; color: var(--accent); }
|
||||
.trust-card { width: 100%; margin-left: auto; margin-right: auto; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 32px 48px; margin-bottom: 24px; }
|
||||
.trust-card .section-label { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 24px; }
|
||||
.trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }
|
||||
.trust-item { font-size: 0.9rem; font-weight: 300; color: var(--text-muted); line-height: 1.6; }
|
||||
.trust-item strong { display: block; font-weight: 600; color: var(--text); margin-bottom: 4px; }
|
||||
.landing-footer { padding: 16px 0; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
|
||||
.landing-footer-left { font-size: 0.9rem; color: var(--text-muted); display: flex; gap: 16px; align-items: center; }
|
||||
.landing-footer-left a { color: var(--text-muted); text-decoration: none; }
|
||||
|
||||
.story-closing {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
color: var(--text);
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.story-closing .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* Trust section */
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 32px 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.trust-card .section-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.trust-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 32px;
|
||||
}
|
||||
.trust-item {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.trust-item strong {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.landing-footer {
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.landing-footer-left {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
.landing-footer-left a {
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
}
|
||||
.landing-footer-left a:hover { color: var(--accent); }
|
||||
.landing-footer-right { font-size: 1rem; }
|
||||
.landing-footer-right .inou { font-weight: 700; color: var(--accent); }
|
||||
.landing-footer-right .health { font-weight: 400; color: var(--text-muted); }
|
||||
@media (max-width: 768px) { .trust-card { padding: 24px; } .trust-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; } }
|
||||
@media (max-width: 480px) { .trust-card { padding: 20px 16px; } .trust-grid { grid-template-columns: 1fr; gap: 20px; } .landing-footer { flex-direction: column; gap: 12px; text-align: center; } .landing-footer-left { flex-direction: column; gap: 8px; } }
|
||||
.landing-footer-right .inou {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
.landing-footer-right .health {
|
||||
font-weight: 400;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto; padding: 24px; }
|
||||
.hero-sources {
|
||||
font-size: 1rem; line-height: 1.8; margin-bottom: 32px; }
|
||||
.hero-pivot { font-size: 1.1rem; margin-bottom: 32px;
|
||||
}
|
||||
.hero-pivot .emphasis { font-size: 1.3rem; }
|
||||
.hero-answer {
|
||||
text-align: center; font-size: 1.2rem; margin-top: 16px;
|
||||
margin-bottom: 8px; }
|
||||
.hero-tagline { font-size: 2rem; margin-bottom: 8px; }
|
||||
.carousel-caption { font-size: 0.85rem; }
|
||||
.hero-cta .btn { padding: 14px 40px; }
|
||||
.story-pair .data { font-size: 1rem; }
|
||||
.story-pair .reality { font-size: 0.95rem; }
|
||||
.trust-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.trust-card {
|
||||
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto; padding: 20px 16px; }
|
||||
.hero-sources {
|
||||
font-size: 0.95rem; line-height: 1.9; }
|
||||
.hero-pivot { font-size: 1rem; }
|
||||
.hero-pivot .emphasis { font-size: 1.2rem; }
|
||||
.story-pair { margin-bottom: 24px; }
|
||||
.trust-grid { grid-template-columns: 1fr; gap: 20px; }
|
||||
.landing-footer { flex-direction: column; gap: 12px; text-align: center; }
|
||||
.landing-footer-left { flex-direction: column; gap: 8px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sg-container">
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="hero">
|
||||
<div class="hero-answer"><span class="inou">inou</span> organiza y comparte tu expediente de salud con tu IA — de forma segura y privada.</div>
|
||||
<div class="hero-tagline">Tu salud, comprendida.</div>
|
||||
<div class="hero-cta">{{if .Dossier}}<a href="/invite" class="btn btn-primary">Invitar a un amigo</a>{{else}}<a href="/start" class="btn btn-primary">Iniciar sesión</a>{{end}}{{if .Error}}<div class="error" style="margin-top: 24px;">{{.Error}}</div>{{end}}</div>
|
||||
<div class="hero-tagline">Tu salud, entendida.</div>
|
||||
<div class="hero-answer">Todos tus datos de salud — organizados, privados y listos para tu IA.</div>
|
||||
<div class="carousel">
|
||||
<div class="carousel-track">
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-1.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-2.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-3.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-4.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-5.webp')"></div>
|
||||
<div class="carousel-slide" style="background-image: url('/static/carousel-6.webp')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-caption" id="carousel-caption">Haz seguimiento de tus tendencias de laboratorio con el tiempo — ve exactamente lo que tu IA ve cuando marca un cambio.</div>
|
||||
<div class="carousel-dots">
|
||||
<button class="carousel-dot active" data-index="0"></button>
|
||||
<button class="carousel-dot" data-index="1"></button>
|
||||
<button class="carousel-dot" data-index="2"></button>
|
||||
<button class="carousel-dot" data-index="3"></button>
|
||||
<button class="carousel-dot" data-index="4"></button>
|
||||
<button class="carousel-dot" data-index="5"></button>
|
||||
</div>
|
||||
<div class="hero-cta">
|
||||
{{if .Dossier}}<a href="/invite" class="btn btn-primary">Invita a un amigo</a>{{else}}<a href="/start" class="btn btn-primary">Iniciar sesión</a>{{end}}
|
||||
{{if .Error}}<div class="error" style="margin-top: 24px;">{{.Error}}</div>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">Necesitas IA para tu salud</h2>
|
||||
|
||||
<div class="story-prose warm">
|
||||
<p>Tus datos de salud están dispersos en docenas de lugares — con tu cardiólogo, tu neurólogo, el laboratorio, tu reloj inteligente, tus apps, tu 23andMe. Y solo tú conoces el resto: qué comes, qué bebes, qué suplementos tomas. Tu rutina de ejercicio. Tus síntomas. Tus objetivos — ya sea que estés intentando quedar embarazada, entrenando para un maratón, o simplemente tratando de sentirte menos cansado.</p>
|
||||
<p>Ya sea que estés sano y quieras seguir así, navegando un diagnóstico difícil, o cuidando a un familiar que no puede defenderse solo — ningún médico ve el panorama completo. Ningún sistema lo conecta.</p>
|
||||
<p>Pero tú tienes acceso a todo. Solo te falta la experiencia para entenderlo todo.</p>
|
||||
<p class="emphasis">Tu IA la tiene. inou le da el panorama completo.</p>
|
||||
<p>Tus datos de salud viven en una docena de lugares diferentes — con tu cardiólogo, tu neurólogo, tu laboratorio, tu reloj, tus aplicaciones, tu 23andMe. Y solo tú conoces el resto: lo que comes, lo que bebes, los suplementos que tomas. Tu rutina de ejercicio. Tus síntomas. Tus objetivos — ya sea que estés intentando quedar embarazada, entrenando para un maratón, o simplemente tratando de sentirte menos agotado.</p>
|
||||
|
||||
<p>Ya sea que estés sano y quieras mantenerte así, navegando un diagnóstico difícil, o cuidando a un familiar que no puede defenderse — ningún médico ve la imagen completa. Ningún sistema lo conecta.</p>
|
||||
|
||||
<p>Pero <strong><em>tú</em></strong> tienes acceso a todo ello. Simplemente no tienes la experiencia para darle sentido.</p>
|
||||
|
||||
<p class="emphasis">Tu IA sí la tiene. inou le da la imagen completa.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">El desafío</h2>
|
||||
<div class="story-pair"><div class="data">Tu resonancia tiene 4.000 cortes.</div><div class="reality">Se leyó en 10 minutos.</div></div>
|
||||
<div class="story-pair"><div class="data">Tu genoma tiene millones de variantes.</div><div class="reality">Solo aprendiste el color de tus ojos y de dónde vienen tus ancestros.</div></div>
|
||||
<div class="story-pair"><div class="data">Tu análisis de sangre tiene docenas de marcadores.</div><div class="reality">Tu médico dijo "todo se ve bien."</div></div>
|
||||
<div class="story-pair"><div class="data">Tu reloj registró 10.000 horas de sueño.</div><div class="reality">Tu entrenador no sabe que existe.</div></div>
|
||||
<div class="story-pair"><div class="data">Has probado cien suplementos diferentes.</div><div class="reality">Nadie preguntó cuáles.</div></div>
|
||||
<div class="story-transition">Las conexiones están ahí.<br>Son demasiado complejas para una sola persona.</div>
|
||||
<div class="story-pair">
|
||||
<div class="data">Tu resonancia magnética tiene 4,000 cortes.</div>
|
||||
<div class="reality">Fue leída en 10 minutos.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Tu genoma tiene millones de variantes.</div>
|
||||
<div class="reality">Lo único que aprendiste fue el color de tus ojos y de dónde vienen tus antepasados.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Tu análisis de sangre tiene docenas de marcadores.</div>
|
||||
<div class="reality">Tu médico dijo "todo está bien".</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Tu reloj rastreó 10,000 horas de sueño.</div>
|
||||
<div class="reality">Tu entrenador no sabe que existe.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-pair">
|
||||
<div class="data">Has intentado cientos de suplementos diferentes.</div>
|
||||
<div class="reality">Nadie preguntó cuáles.</div>
|
||||
</div>
|
||||
|
||||
<div class="story-transition">
|
||||
Las conexiones están ahí.<br>
|
||||
Simplemente son demasiado complejas para que una sola persona las comprenda.
|
||||
</div>
|
||||
|
||||
<div class="story-gaps">
|
||||
<span>Nadie sabe cómo tu cuerpo procesa la Warfarina — ni siquiera tú.</span>
|
||||
<span class="indent">Pero la respuesta podría estar escondida en tu 23andMe.</span>
|
||||
<span>Ese "sin hallazgos" en tu resonancia — ¿alguien miró cuidadosamente los 4.000 cortes?</span>
|
||||
<span>Tu tiroides está "dentro del rango" — pero nadie lo conectó con tu fatiga, tu peso, que siempre tienes frío.</span>
|
||||
<span class="indent">Pero la respuesta ya podría estar oculta en tu 23andMe.</span>
|
||||
<span>Ese 'sin hallazgos significativos' en tu resonancia magnética — ¿alguien miró de cerca los 4,000 cortes?</span>
|
||||
<span>Tu tiroides está 'dentro del rango' — pero nadie la conectó con tu fatiga, tu peso, siempre tener frío.</span>
|
||||
</div>
|
||||
|
||||
<div class="story-connections">
|
||||
<span>Nadie conecta tu café de la tarde con tu calidad de sueño.</span>
|
||||
<span>Tus niveles de hierro con tu fatiga en el entrenamiento.</span>
|
||||
<span>Nadie está conectando tu cafeína de la tarde con tus puntuaciones de sueño.</span>
|
||||
<span>Tus niveles de hierro con tu fatiga durante el ejercicio.</span>
|
||||
<span>Tu genética con tu niebla mental.</span>
|
||||
</div>
|
||||
|
||||
<div class="story-ai">
|
||||
<span>Tu IA no olvida.</span>
|
||||
<span>No se apresura.</span>
|
||||
<span>Encuentra lo que se pasó por alto.</span>
|
||||
<span>No tiene prisa.</span>
|
||||
<span>Encuentra lo que se perdió.</span>
|
||||
<span class="last">No se especializa — te ve completo.</span>
|
||||
</div>
|
||||
<div class="story-closing"><span class="inou">inou</span> permite que tu IA tome todo en cuenta — cada corte, cada marcador, cada variante — conecta todo y finalmente te da respuestas que nadie más podía dar.</div>
|
||||
|
||||
<div class="story-closing"><span class="inou">inou</span> permite que tu IA lo tenga todo en cuenta — cada corte, cada marcador, cada variante — conecta todo y finalmente te da respuestas que nadie más podría darte.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="landing-card">
|
||||
<div class="story">
|
||||
<h2 class="story-title">Por qué construimos esto</h2>
|
||||
<p class="story-prose">Has recopilado años de datos de salud. Estudios del hospital. Análisis del laboratorio. Resultados del portal del médico. Datos de tu reloj. Quizás incluso tu ADN.</p>
|
||||
<p class="story-prose">Y luego está todo lo que solo tú sabes — tu peso, tu presión arterial, tu programa de entrenamiento, los suplementos que tomas, los síntomas que siempre olvidas mencionar.</p>
|
||||
<p class="story-prose">Todo está ahí — pero disperso en sistemas que no se comunican, con especialistas que solo ven su parte, o encerrado en tu propia cabeza.</p>
|
||||
<p class="story-prose">Tu cardiólogo no sabe lo que encontró tu neurólogo. Tu entrenador no ha visto tus análisis de sangre. Tu médico no tiene idea de qué suplementos tomas. Y ninguno de ellos tiene tiempo para sentarse contigo y conectar los puntos.</p>
|
||||
<p class="story-prose"><strong>La IA finalmente puede.</strong> Puede unir lo que ningún experto solo ve — y además explicártelo.</p>
|
||||
<p class="story-prose">Pero estos datos no caben en una ventana de chat. Y lo último que quieres es tu historial médico en los servidores de alguien más, entrenando sus modelos.</p>
|
||||
<p class="story-prose"><span class="inou">inou</span> lo une todo — laboratorio, imágenes, genética, signos vitales, medicamentos, suplementos — encriptado, privado, y sin compartir con absolutamente nadie. Tu IA se conecta de forma segura. Tus datos siguen siendo tuyos.</p>
|
||||
<div class="story-closing">Tu salud, comprendida.</div>
|
||||
|
||||
<p class="story-prose">Has recopilado años de datos de salud. Exploraciones del hospital. Análisis de sangre del laboratorio. Resultados del portal de tu médico. Datos de tu reloj. Quizás incluso tu ADN.</p>
|
||||
|
||||
<p class="story-prose">Y luego está todo lo que solo tú conoces — tu peso, tu presión arterial, tu calendario de entrenamiento, los suplementos que tomas, los síntomas que has estado pensando mencionar.</p>
|
||||
|
||||
<p class="story-prose">Todo está ahí — pero disperso en sistemas que no se hablan, en manos de especialistas que solo ven su parte, o bloqueado en tu propia cabeza.</p>
|
||||
|
||||
<p class="story-prose">Tu cardiólogo no sabe lo que encontró tu neurólogo. Tu entrenador no ha visto tus análisis de sangre. Tu médico no tiene idea de qué suplementos estás tomando. Y ninguno de ellos tiene tiempo para sentarse contigo y conectar los puntos.</p>
|
||||
|
||||
<p class="story-prose"><strong>La IA finalmente puede.</strong> Puede sintetizar lo que ningún experto individual ve — y realmente explicártelo.</p>
|
||||
|
||||
<p class="story-prose">Pero estos datos no caben en una ventana de chat. Y lo último que quieres es tu historial médico en los servidores de otra persona, entrenando sus modelos.</p>
|
||||
|
||||
<p class="story-prose"><span class="inou">inou</span> une todo — laboratorios, imágenes, genética, signos vitales, medicamentos, suplementos — encriptado, privado y compartido con absolutamente nadie. Tu IA se conecta de forma segura. Tus datos siguen siendo tuyos.</p>
|
||||
|
||||
<div class="story-closing">Tu salud, entendida.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="trust-card">
|
||||
<div class="section-label">{{.T.data_yours}}</div>
|
||||
<div class="trust-grid">
|
||||
<div class="trust-item"><strong>{{.T.never_training}}</strong>{{.T.never_training_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.never_shared}}</strong>{{.T.never_shared_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.encrypted}}</strong>{{.T.encrypted_desc}}</div>
|
||||
<div class="trust-item"><strong>{{.T.delete}}</strong>{{.T.delete_desc}}</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.never_training}}</strong>
|
||||
{{.T.never_training_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.never_shared}}</strong>
|
||||
{{.T.never_shared_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.encrypted}}</strong>
|
||||
{{.T.encrypted_desc}}
|
||||
</div>
|
||||
<div class="trust-item">
|
||||
<strong>{{.T.delete}}</strong>
|
||||
{{.T.delete_desc}}
|
||||
</div>
|
||||
</div>
|
||||
<footer class="landing-footer">
|
||||
<div class="landing-footer-left"><span>© 2025</span><a href="/privacy-policy">Privacidad</a></div>
|
||||
<span class="landing-footer-right"><span class="inou">inou</span> <span class="health">health</span></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var track = document.querySelector('.carousel-track');
|
||||
var dots = document.querySelectorAll('.carousel-dot');
|
||||
var caption = document.getElementById('carousel-caption');
|
||||
var captions = [
|
||||
'Haz seguimiento de tus tendencias de laboratorio con el tiempo — ve exactamente lo que tu IA ve cuando marca un cambio.',
|
||||
'Tus laboratorios, exploraciones y genoma en un solo lugar — explora todo a lo que tu IA tiene acceso.',
|
||||
'Ve tu propia resonancia magnética — amplía los mismos cortes que analizó tu IA.',
|
||||
'Tu exploración cerebral en 3D — navega cada plano, verifica cada hallazgo que hizo tu IA.',
|
||||
'Tu IA conecta los puntos entre laboratorios y genoma — y lo explica en lenguaje sencillo.',
|
||||
'Tu radiografía, resolución completa — amplía los hallazgos que marcó tu IA.'
|
||||
];
|
||||
var count = dots.length;
|
||||
var current = 0;
|
||||
function go(i) {
|
||||
current = i;
|
||||
track.style.transform = 'translateX(-' + (i * 100) + '%)';
|
||||
dots.forEach(function(d, j) { d.classList.toggle('active', j === i); });
|
||||
caption.textContent = captions[i];
|
||||
}
|
||||
dots.forEach(function(d) {
|
||||
d.addEventListener('click', function() { go(+d.dataset.index); });
|
||||
});
|
||||
setInterval(function() { go((current + 1) % count); }, 8000);
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
{{define "pricing_da"}}
|
||||
<style>
|
||||
.pricing-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
text-align: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.pricing-header h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.pricing-header .tagline {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pricing-table-wrapper {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.pricing-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.pricing-table thead {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.pricing-table th {
|
||||
padding: 24px 16px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table th:first-child {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.tier-price .free {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.tier-price .small {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-price s {
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-free {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #28a745;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.pricing-table tbody tr {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.pricing-table td {
|
||||
padding: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.feature-name {
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.feature-cell {
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.check {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.category-row {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.category-row td {
|
||||
padding: 16px 16px;
|
||||
font-size: 1.1rem;
|
||||
border-left: 3px solid var(--accent);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.pricing-container { padding: 24px 16px 48px; }
|
||||
.pricing-header h1 { font-size: 2rem; }
|
||||
.pricing-table th { padding: 16px 12px; }
|
||||
.pricing-table td { padding: 12px; }
|
||||
.tier-name { font-size: 1rem; }
|
||||
.tier-price { font-size: 1.5rem; }
|
||||
.feature-name { font-size: 0.9rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pricing-container { padding: 16px 12px 32px; }
|
||||
.pricing-header h1 { font-size: 1.75rem; }
|
||||
.pricing-table th:first-child { width: 35%; }
|
||||
.tier-name { font-size: 0.9rem; }
|
||||
.tier-price { font-size: 1.25rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="pricing-container">
|
||||
<div class="pricing-header">
|
||||
<h1>Priser</h1>
|
||||
<p class="tagline">Alle niveauer er gratis indtil 1. juli 2026. Intet kreditkort kræves.</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing-table-wrapper">
|
||||
<table class="pricing-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Overvågning</div>
|
||||
<div class="tier-price"><span class="free">Gratis</span></div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Optimering</div>
|
||||
<div class="tier-price"><s>$12<span class="small">/md</span></s></div>
|
||||
<div class="tier-free">gratis indtil 1/7/26</div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Forskning</div>
|
||||
<div class="tier-price"><s>$35<span class="small">/md</span></s></div>
|
||||
<div class="tier-free">gratis til 1/7/26</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Sundhedsdata</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Vitalparametre (blodtryk, puls, vægt, temp)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Symptomer og tilstande</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Medicin</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Motion og aktivitet</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Familiehistorik</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Laboratorieresultater</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Forbrugergenom (23andMe)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Medicinsk billeddannelse (MR, CT, røntgen)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Klinisk genomsekventering</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">AI-funktioner</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">MCP-integration (Claude, ChatGPT)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Personaliserede AI-svar</td>
|
||||
<td class="feature-cell">Begrænset</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Sundhedstendensanalyse</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Opbevaring og adgang</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Understøttelse af flere mapper (familie)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">FIPS 140-3 kryptering</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Dataeksport</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
{{define "pricing_de"}}
|
||||
<style>
|
||||
.pricing-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
text-align: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.pricing-header h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.pricing-header .tagline {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pricing-table-wrapper {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.pricing-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.pricing-table thead {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.pricing-table th {
|
||||
padding: 24px 16px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table th:first-child {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.tier-price .free {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.tier-price .small {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-price s {
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-free {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #28a745;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.pricing-table tbody tr {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.pricing-table td {
|
||||
padding: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.feature-name {
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.feature-cell {
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.check {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.category-row {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.category-row td {
|
||||
padding: 16px 16px;
|
||||
font-size: 1.1rem;
|
||||
border-left: 3px solid var(--accent);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.pricing-container { padding: 24px 16px 48px; }
|
||||
.pricing-header h1 { font-size: 2rem; }
|
||||
.pricing-table th { padding: 16px 12px; }
|
||||
.pricing-table td { padding: 12px; }
|
||||
.tier-name { font-size: 1rem; }
|
||||
.tier-price { font-size: 1.5rem; }
|
||||
.feature-name { font-size: 0.9rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pricing-container { padding: 16px 12px 32px; }
|
||||
.pricing-header h1 { font-size: 1.75rem; }
|
||||
.pricing-table th:first-child { width: 35%; }
|
||||
.tier-name { font-size: 0.9rem; }
|
||||
.tier-price { font-size: 1.25rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="pricing-container">
|
||||
<div class="pricing-header">
|
||||
<h1>Preise</h1>
|
||||
<p class="tagline">Alle Stufen sind bis zum 1. Juli 2026 kostenlos. Keine Kreditkarte erforderlich.</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing-table-wrapper">
|
||||
<table class="pricing-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Monitor</div>
|
||||
<div class="tier-price"><span class="free">Kostenlos</span></div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Optimize</div>
|
||||
<div class="tier-price"><s>$12<span class="small">/Monat</span></s></div>
|
||||
<div class="tier-free">kostenlos bis 1. Juli 2026</div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Research</div>
|
||||
<div class="tier-price"><s>$35<span class="small">/Monat</span></s></div>
|
||||
<div class="tier-free">kostenlos bis 1. Juli 2026</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Gesundheitsdaten</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Vitalparameter (BP, HR, Gewicht, Temperatur)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Symptome & Zustände</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Medikamente</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Bewegung & Aktivität</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Familienanamnese</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Laborergebnisse</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Konsumenten-Genom (23andMe)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Medizinische Bildgebung (MRI, CT, Röntgen)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Klinische Genomsequenzierung</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">KI-Funktionen</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">MCP-Integration (Claude, ChatGPT)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Personalisierte KI-Antworten</td>
|
||||
<td class="feature-cell">Begrenzt</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Gesundheitstrend-Analyse</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Speicherung & Zugriff</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Mehrfach-Dossier-Unterstützung (Familie)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">FIPS 140-3 Verschlüsselung</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Datenexport</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
{{define "pricing_es"}}
|
||||
<style>
|
||||
.pricing-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
text-align: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.pricing-header h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.pricing-header .tagline {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pricing-table-wrapper {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.pricing-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.pricing-table thead {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.pricing-table th {
|
||||
padding: 24px 16px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table th:first-child {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.tier-price .free {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.tier-price .small {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-price s {
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-free {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #28a745;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.pricing-table tbody tr {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.pricing-table td {
|
||||
padding: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.feature-name {
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.feature-cell {
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.check {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.category-row {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.category-row td {
|
||||
padding: 16px 16px;
|
||||
font-size: 1.1rem;
|
||||
border-left: 3px solid var(--accent);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.pricing-container { padding: 24px 16px 48px; }
|
||||
.pricing-header h1 { font-size: 2rem; }
|
||||
.pricing-table th { padding: 16px 12px; }
|
||||
.pricing-table td { padding: 12px; }
|
||||
.tier-name { font-size: 1rem; }
|
||||
.tier-price { font-size: 1.5rem; }
|
||||
.feature-name { font-size: 0.9rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pricing-container { padding: 16px 12px 32px; }
|
||||
.pricing-header h1 { font-size: 1.75rem; }
|
||||
.pricing-table th:first-child { width: 35%; }
|
||||
.tier-name { font-size: 0.9rem; }
|
||||
.tier-price { font-size: 1.25rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="pricing-container">
|
||||
<div class="pricing-header">
|
||||
<h1>Precios</h1>
|
||||
<p class="tagline">Todos los niveles son gratuitos hasta el 1 de julio de 2026. No se requiere tarjeta de crédito.</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing-table-wrapper">
|
||||
<table class="pricing-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Monitor</div>
|
||||
<div class="tier-price"><span class="free">Gratis</span></div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Optimizar</div>
|
||||
<div class="tier-price"><s>$12<span class="small">/mes</span></s></div>
|
||||
<div class="tier-free">gratis hasta 1/7/26</div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">Investigación</div>
|
||||
<div class="tier-price"><s>$35<span class="small">/mes</span></s></div>
|
||||
<div class="tier-free">gratis hasta 1/7/26</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Datos de salud</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Signos vitales (PA, FC, peso, temp)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Síntomas y condiciones</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Medicamentos</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Ejercicio y actividad</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Historial familiar</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Resultados de laboratorio</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Genoma del consumidor (23andMe)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Imágenes médicas (IRM, TC, rayos X)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Secuenciación genómica clínica</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Funciones de IA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Integración MCP (Claude, ChatGPT)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Respuestas de IA personalizadas</td>
|
||||
<td class="feature-cell">Limitado</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Análisis de tendencias de salud</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">Almacenamiento y acceso</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Soporte multi-expediente (familia)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Cifrado FIPS 140-3</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">Exportación de datos</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
{{define "pricing_ja"}}
|
||||
<style>
|
||||
.pricing-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
text-align: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.pricing-header h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.pricing-header .tagline {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pricing-table-wrapper {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.pricing-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.pricing-table thead {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.pricing-table th {
|
||||
padding: 24px 16px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table th:first-child {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.tier-price .free {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.tier-price .small {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-price s {
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tier-free {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #28a745;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.pricing-table tbody tr {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.pricing-table tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.pricing-table td {
|
||||
padding: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.feature-name {
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.feature-cell {
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.check {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.category-row {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.category-row td {
|
||||
padding: 16px 16px;
|
||||
font-size: 1.1rem;
|
||||
border-left: 3px solid var(--accent);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.pricing-container { padding: 24px 16px 48px; }
|
||||
.pricing-header h1 { font-size: 2rem; }
|
||||
.pricing-table th { padding: 16px 12px; }
|
||||
.pricing-table td { padding: 12px; }
|
||||
.tier-name { font-size: 1rem; }
|
||||
.tier-price { font-size: 1.5rem; }
|
||||
.feature-name { font-size: 0.9rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pricing-container { padding: 16px 12px 32px; }
|
||||
.pricing-header h1 { font-size: 1.75rem; }
|
||||
.pricing-table th:first-child { width: 35%; }
|
||||
.tier-name { font-size: 0.9rem; }
|
||||
.tier-price { font-size: 1.25rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="pricing-container">
|
||||
<div class="pricing-header">
|
||||
<h1>料金プラン</h1>
|
||||
<p class="tagline">2026年7月1日まで全プラン無料です。クレジットカードは不要です。</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing-table-wrapper">
|
||||
<table class="pricing-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">モニター</div>
|
||||
<div class="tier-price"><span class="free">無料</span></div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">最適化</div>
|
||||
<div class="tier-price"><s>$12<span class="small">/月</span></s></div>
|
||||
<div class="tier-free">26/7/1まで無料</div>
|
||||
</th>
|
||||
<th class="tier-header">
|
||||
<div class="tier-name">リサーチ</div>
|
||||
<div class="tier-price"><s>$35<span class="small">/月</span></s></div>
|
||||
<div class="tier-free">26/7/1まで無料</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td colspan="4">健康データ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">バイタルサイン(血圧、心拍、体重、体温)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">症状と病状</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">薬</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">運動とアクティビティ</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">家族歴</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">検査結果</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">コンシューマーゲノム(23andMe)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">医用画像(MRI、CT、X線)</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">臨床ゲノムシーケンス</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">AI機能</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">MCP連携(Claude、ChatGPT)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">パーソナライズされたAI回答</td>
|
||||
<td class="feature-cell">制限あり</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">健康トレンド分析</td>
|
||||
<td class="feature-cell cross">✗</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category-row">
|
||||
<td colspan="4">ストレージとアクセス</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">マルチドシエサポート(家族)</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">FIPS 140-3 暗号化</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-name">データエクスポート</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
<td class="feature-cell check">✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
{{define "terms_de"}}
|
||||
<style>
|
||||
.terms-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 80px;
|
||||
}
|
||||
|
||||
.terms-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.terms-card h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.terms-card .intro {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.terms-card h2 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-top: 0;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.terms-card h3 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-top: 24px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.terms-card h3:first-child { margin-top: 0; }
|
||||
|
||||
.terms-card p {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.terms-card p:last-child { margin-bottom: 0; }
|
||||
|
||||
.terms-card strong {
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.terms-card a {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.inou-brand {
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.terms-container { padding: 24px 16px 48px; }
|
||||
.terms-card { padding: 32px 24px; }
|
||||
.terms-card h1 { font-size: 2rem; }
|
||||
.terms-card .intro { font-size: 1.05rem; }
|
||||
.terms-card h2 { font-size: 1.25rem; }
|
||||
.terms-card h3 { font-size: 1rem; }
|
||||
.terms-card p { font-size: 0.95rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.terms-container { padding: 16px 12px 32px; }
|
||||
.terms-card { padding: 24px 16px; }
|
||||
.terms-card h1 { font-size: 1.75rem; }
|
||||
.terms-card .intro { font-size: 1rem; }
|
||||
.terms-card h2 { font-size: 1.15rem; }
|
||||
.terms-card p { font-size: 0.9rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="terms-container">
|
||||
|
||||
<div class="terms-card">
|
||||
<h1>Nutzungsbedingungen</h1>
|
||||
<p class="intro">Diese Bedingungen regeln deine Nutzung von <span class="inou-brand">inou</span>. Durch das Erstellen eines Kontos stimmst du ihnen zu. Wenn du nicht zustimmst, nutze den Service nicht.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Der Service</h2>
|
||||
|
||||
<h3>Was inou ist.</h3>
|
||||
<p><span class="inou-brand">inou</span> ist eine persönliche Gesundheitsdatenplattform. Du lädst deine medizinischen Dateien hoch – Bildgebung, Laborergebnisse, genetische Daten – und wir speichern sie sicher, damit du sie ansehen und verwalten kannst. Du kannst Drittanbieter-Tools, wie z. B. KI‑Assistenten, verbinden, um auf deine Daten zuzugreifen.</p>
|
||||
|
||||
<h3>Was inou nicht ist.</h3>
|
||||
<p><span class="inou-brand">inou</span> ist kein medizinisches Gerät. Es ist nicht für klinische Diagnosen, Behandlungen, Heilungen oder Prävention von Krankheiten oder medizinischen Zuständen bestimmt. <span class="inou-brand">inou</span> gibt keine medizinischen Ratschläge. Die Plattform zeigt deine Daten – sie interpretiert sie nicht, empfiehlt keine Maßnahmen oder ersetzt einen qualifizierten Gesundheitsfachmann. Konsultiere immer deinen Arzt für medizinische Entscheidungen.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Dein Konto</h2>
|
||||
|
||||
<h3>Kontobestimmungen.</h3>
|
||||
<p>Du musst mindestens 18 Jahre alt sein, um ein Konto zu erstellen, es sei denn, ein Elternteil oder Erziehungsberechtigter erstellt und verwaltet das Konto in deinem Namen. Du bist dafür verantwortlich, deine Zugangsdaten sicher aufzubewahren. Ein Konto pro Person – Konten sind nicht übertragbar.</p>
|
||||
|
||||
<h3>Deine Daten, deine Verantwortung.</h3>
|
||||
<p>Du bist für die Genauigkeit und Rechtsmäßigkeit der hochgeladenen Daten verantwortlich. Du musst das Recht haben, die hochgeladenen Dateien zu speichern und zu verarbeiten. Lade keine Daten anderer hoch, ohne deren ausdrückliche Zustimmung.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Unsere Verantwortlichkeiten</h2>
|
||||
|
||||
<h3>Was wir bereitstellen.</h3>
|
||||
<p>Wir speichern deine Daten sicher unter Verwendung von FIPS 140‑3 validierter Verschlüsselung, stellen sie dir über die Plattform zur Verfügung und übertragen sie an Drittanbieter-Dienste, die du ausdrücklich autorisierst. Weitere Informationen zum Schutz deiner Daten findest du auf unserer <a href="/security">Sicherheitsseite</a>. Wir informieren dich über wesentliche Änderungen dieser Bedingungen oder unserer Datenschutzpraktiken.</p>
|
||||
|
||||
<h3>Was wir nicht garantieren.</h3>
|
||||
<p>Wir streben nach kontinuierlicher Verfügbarkeit, können sie jedoch nicht garantieren. Der Service kann vorübergehend wegen Wartung, Updates oder unvorhersehbarer Umstände nicht verfügbar sein. Wir haften nicht für Entscheidungen, die du oder andere auf Basis der über die Plattform angesehenen Daten treffen.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Datenschutz und Datenverarbeitung</h2>
|
||||
<p>Deine Nutzung von <span class="inou-brand">inou</span> unterliegt unserer <a href="/privacy-policy">Datenschutzerklärung</a> und dem <a href="/legal/dpa">Auftragsverarbeitungsvertrag</a>, die beschreiben, welche Daten wir erfassen, wie wir sie nutzen und welche Rechte du hast. Durch die Nutzung des Service erkennst du diese Bedingungen an und stimmst ihnen zu.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Akzeptabler Gebrauch</h2>
|
||||
|
||||
<h3>Nicht.</h3>
|
||||
<p>Versuche nicht, auf Daten anderer Nutzer zuzugreifen. Reversiere, prüfe oder attackiere die Plattform nicht. Verwende den Service nicht für illegale Zwecke. Lade keine bösartigen Dateien hoch. Lade keine Inhalte hoch, die nicht mit Gesundheitsdaten zusammenhängen – dies ist eine medizinische Plattform, kein allgemeines Speichersystem. Teile deine Zugangsdaten nicht. Verkaufe keinen Zugang zum Service weiter.</p>
|
||||
|
||||
<h3>Wenn du das tust.</h3>
|
||||
<p>Wir können dein Konto suspendieren oder kündigen. Bei illegalen Aktivitäten werden wir mit den Strafverfolgungsbehörden zusammenarbeiten.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Geistiges Eigentum</h2>
|
||||
<p>Deine Daten gehören dir. Du behältst alle Rechte an den Gesundheitsdaten, Dateien und Informationen, die du hochlädst. Wir beanspruchen kein Eigentum an deinem Inhalt.</p>
|
||||
<p>Die <span class="inou-brand">inou</span>-Plattform – ihre Software, ihr Design, ihre Marken und Dokumentation – gehört uns. Diese Bedingungen gewähren dir eine persönliche, nicht‑exklusive, nicht übertragbare Lizenz zur Nutzung des Service. Sie gewähren dir keine Rechte an unserem Code, Design oder unserer Marke.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Bezahlung</h2>
|
||||
|
||||
<h3>Preise.</h3>
|
||||
<p>Pläne und Preise werden auf unserer <a href="/pricing">Preisseite</a> beschrieben. Die Preise können sich ändern – wir informieren dich im Voraus über jede Erhöhung. Die Zahlung wird von Drittanbietern abgewickelt. Wir sehen oder speichern deine Zahlungsdetails nie.</p>
|
||||
|
||||
<h3>Rückerstattungen.</h3>
|
||||
<p>Wenn du unzufrieden bist, kontaktiere uns. Wir bearbeiten Rückerstattungen individuell.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Kündigung</h2>
|
||||
|
||||
<h3>Du kannst jederzeit kündigen.</h3>
|
||||
<p>Lösche dein Konto, und alle deine Daten werden dauerhaft gelöscht. Keine Benachrichtigung erforderlich. Keine Strafe.</p>
|
||||
|
||||
<h3>Wir können ebenfalls kündigen.</h3>
|
||||
<p>Wir können dein Konto wegen Verstoßes gegen diese Bedingungen kündigen, sofern möglich, mit Vorankündigung. Wenn wir den Service vollständig einstellen, geben wir dir angemessene Zeit, deine Daten zu exportieren.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Haftung</h2>
|
||||
|
||||
<h3>Haftungsbeschränkung.</h3>
|
||||
<p>In dem maximalen Umfang, der gesetzlich zulässig ist, ist die Gesamthaftung von <span class="inou-brand">inou</span> dir gegenüber für jegliche Ansprüche, die sich aus diesen Bedingungen oder dem Service ergeben, auf den Betrag begrenzt, den du in den 12 Monaten vor dem Anspruch an uns gezahlt hast. Wir haften nicht für indirekte, beiläufige, besondere, Folgeschäden oder Strafschäden.</p>
|
||||
|
||||
<h3>Entschädigung.</h3>
|
||||
<p>Du verpflichtest dich, <span class="inou-brand">inou</span> gegen Ansprüche zu entschädigen, die sich aus deiner Nutzung des Service, deinen Daten oder deinem Verstoß gegen diese Bedingungen ergeben.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Anwendbares Recht</h2>
|
||||
<p>Diese Bedingungen unterliegen den Gesetzen des Bundesstaates Florida, USA. Streitigkeiten werden vor den Gerichten Floridas entschieden.</p>
|
||||
</div>
|
||||
|
||||
<div class="terms-card">
|
||||
<h2>Änderungen</h2>
|
||||
<p>Wir können diese Bedingungen aktualisieren. Registrierte Nutzer werden per E‑Mail über wesentliche Änderungen informiert. Die fortgesetzte Nutzung nach Änderungen gilt als Zustimmung.</p>
|
||||
<p>Datenschutzbeauftragter: <a href="mailto:privacy@inou.com">privacy@inou.com</a></p>
|
||||
<p>Zuletzt aktualisiert: 8. Februar 2026.</p>
|
||||
</div>
|
||||
|
||||
{{template "footer"}}
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
// translate: MiniMax M2.5 draft → GLM 5 review → write
|
||||
//
|
||||
// translate --lang de --what faq
|
||||
// translate --lang all --what all
|
||||
// translate --lang de --what yaml --no-review
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const apiURL = "https://openrouter.ai/api/v1/chat/completions"
|
||||
|
||||
var (
|
||||
translateModel = "openai/gpt-oss-20b:nitro"
|
||||
reviewModel = "z-ai/glm-5"
|
||||
apiKey string
|
||||
)
|
||||
|
||||
var langName = map[string]string{
|
||||
"da": "Danish", "de": "German", "es": "Spanish", "fi": "Finnish",
|
||||
"fr": "French", "hi": "Hindi", "id": "Indonesian", "it": "Italian",
|
||||
"ja": "Japanese", "ko": "Korean", "nl": "Dutch", "no": "Norwegian",
|
||||
"pl": "Polish", "pt": "Portuguese", "ru": "Russian", "sv": "Swedish",
|
||||
"th": "Thai", "tr": "Turkish", "uk": "Ukrainian", "vi": "Vietnamese",
|
||||
"zh": "Chinese (Simplified)",
|
||||
}
|
||||
|
||||
var langNative = map[string]string{
|
||||
"da": "Dansk", "de": "Deutsch", "es": "Español", "fi": "Suomi",
|
||||
"fr": "Français", "hi": "हिन्दी", "id": "Bahasa Indonesia", "it": "Italiano",
|
||||
"ja": "日本語", "ko": "한국어", "nl": "Nederlands", "no": "Norsk",
|
||||
"pl": "Polski", "pt": "Português", "ru": "Русский", "sv": "Svenska",
|
||||
"th": "ไทย", "tr": "Türkçe", "uk": "Українська", "vi": "Tiếng Việt",
|
||||
"zh": "中文",
|
||||
}
|
||||
|
||||
var langAddress = map[string]string{
|
||||
"da": "du/din", "de": "du/dein (informal)", "es": "tú (informal)",
|
||||
"fr": "tu/ton (informal)", "hi": "तुम (informal)", "id": "kamu (informal)",
|
||||
"it": "tu (informal)", "ja": "polite form (です/ます)", "ko": "존댓말 (polite)",
|
||||
"nl": "je/jouw (informal)", "no": "du/din", "pl": "ty (informal)",
|
||||
"pt": "você", "ru": "ты (informal)", "sv": "du/din", "th": "คุณ (polite)",
|
||||
"tr": "sen (informal)", "uk": "ти (informal)", "vi": "bạn (informal)",
|
||||
"zh": "你 (informal)",
|
||||
}
|
||||
|
||||
var knownTemplates = []string{"landing", "faq", "pricing", "privacy", "security", "dpa", "terms", "connect", "docs", "consent"}
|
||||
|
||||
func main() {
|
||||
lang := flag.String("lang", "", "language(s) or 'all'")
|
||||
what := flag.String("what", "", "template name(s), 'yaml', or 'all'")
|
||||
key := flag.String("key", "", "OpenRouter API key")
|
||||
portal := flag.String("portal", "", "portal directory")
|
||||
noReview := flag.Bool("no-review", false, "skip review pass")
|
||||
flag.Parse()
|
||||
|
||||
apiKey = pick(*key, os.Getenv("OPENROUTER_API_KEY"), envKey("OPENROUTER_API_KEY"))
|
||||
if apiKey == "" {
|
||||
die("no API key")
|
||||
}
|
||||
portalDir := *portal
|
||||
if portalDir == "" {
|
||||
portalDir = findPortalDir()
|
||||
}
|
||||
if *lang == "" || *what == "" {
|
||||
die("Usage: translate --lang <code|all> --what <name|yaml|all>")
|
||||
}
|
||||
|
||||
langs := resolveLangs(*lang)
|
||||
tmpls, doYAML := resolveWhat(*what)
|
||||
review := !*noReview
|
||||
total := len(langs) * (len(tmpls) + b2i(doYAML))
|
||||
n, errors := 0, 0
|
||||
|
||||
for _, l := range langs {
|
||||
for _, t := range tmpls {
|
||||
n++
|
||||
fmt.Printf("[%d/%d] %s/%s ", n, total, l, t)
|
||||
if err := doTemplate(portalDir, l, t, review); err != nil {
|
||||
fmt.Printf("ERROR: %v\n", err)
|
||||
errors++
|
||||
}
|
||||
}
|
||||
if doYAML {
|
||||
n++
|
||||
fmt.Printf("[%d/%d] %s/yaml ", n, total, l)
|
||||
if err := doYAML_(portalDir, l, review); err != nil {
|
||||
fmt.Printf("ERROR: %v\n", err)
|
||||
errors++
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("\nDone: %d/%d succeeded\n", total-errors, total)
|
||||
if errors > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Template ---
|
||||
|
||||
func doTemplate(portalDir, lang, name string, review bool) error {
|
||||
src, err := os.ReadFile(filepath.Join(portalDir, "templates", name+".tmpl"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ln, addr := langName[lang], langAddress[lang]
|
||||
|
||||
prompt := fmt.Sprintf(`Translate this web page template from English to %s.
|
||||
RULES:
|
||||
- Preserve ALL HTML tags, attributes, classes, IDs exactly
|
||||
- Preserve ALL Go template syntax ({{.T.key}}, {{range}}, {{end}}, {{if}}, etc.)
|
||||
- Preserve ALL JavaScript and CSS untranslated
|
||||
- Never translate "inou"
|
||||
- Keep English loanwords %s speakers actually use
|
||||
- Use %s address forms
|
||||
- Keep technical terms: DICOM, MRI, CT, FLAIR, MCP, API, JSON, CSV, HIPAA, GDPR, OCR, PDF
|
||||
- Rename {{define "X"}} to {{define "X_%s"}}
|
||||
- Output ONLY the translated template`, ln, ln, addr, lang)
|
||||
|
||||
fmt.Printf("draft... ")
|
||||
translated, err := callLLM(translateModel, prompt, string(src), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
translated = stripFences(translated)
|
||||
translated = ensureDefine(translated, name, lang)
|
||||
|
||||
if review {
|
||||
fmt.Printf("GLM review... ")
|
||||
translated = reviewContent(translated, ln, "template")
|
||||
}
|
||||
|
||||
os.WriteFile(filepath.Join(portalDir, "templates", name+"_"+lang+".tmpl"), []byte(translated), 0644)
|
||||
fmt.Println("ok")
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- YAML ---
|
||||
|
||||
func doYAML_(portalDir, lang string, review bool) error {
|
||||
src, err := os.ReadFile(filepath.Join(portalDir, "lang", "en.yaml"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ln, addr := langName[lang], langAddress[lang]
|
||||
|
||||
allKeys := extractKeys(string(src))
|
||||
keys := make(map[string]string)
|
||||
passthrough := make(map[string]string)
|
||||
for k, v := range allKeys {
|
||||
switch {
|
||||
case strings.HasPrefix(k, "lang_"):
|
||||
passthrough[k] = v
|
||||
case k == "language_name":
|
||||
passthrough[k] = langNative[lang]
|
||||
default:
|
||||
keys[k] = v
|
||||
}
|
||||
}
|
||||
keysJSON, _ := json.Marshal(keys)
|
||||
|
||||
prompt := fmt.Sprintf(`Translate these UI strings from English to %s.
|
||||
Return a JSON object with same keys and translated values.
|
||||
RULES: keep format placeholders (%%s %%d), never translate "inou", use %s address, keep technical terms.
|
||||
Return ONLY valid JSON.`, ln, addr)
|
||||
|
||||
fmt.Printf("draft... ")
|
||||
result, err := callLLM(translateModel, prompt, string(keysJSON), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result = stripFences(result)
|
||||
|
||||
var translated map[string]string
|
||||
if err := json.Unmarshal([]byte(result), &translated); err != nil {
|
||||
return fmt.Errorf("bad JSON: %w", err)
|
||||
}
|
||||
|
||||
if review {
|
||||
fmt.Printf("GLM review... ")
|
||||
reviewYAML_(keys, translated, ln)
|
||||
}
|
||||
|
||||
for k, v := range passthrough {
|
||||
translated[k] = v
|
||||
}
|
||||
os.WriteFile(filepath.Join(portalDir, "lang", lang+".yaml"), []byte(rebuildYAML(string(src), translated)), 0644)
|
||||
fmt.Println("ok")
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- LLM call ---
|
||||
|
||||
func callLLM(model, system, user string, maxTokHint int) (string, error) {
|
||||
body := map[string]any{
|
||||
"model": model,
|
||||
"messages": []map[string]string{{"role": "system", "content": system}, {"role": "user", "content": user}},
|
||||
"temperature": 0.1,
|
||||
"provider": map[string]any{"order": []string{"Groq"}, "allow_fallbacks": true},
|
||||
}
|
||||
if maxTokHint > 0 {
|
||||
body["max_tokens"] = maxTokHint
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(body)
|
||||
req, _ := http.NewRequest("POST", apiURL, bytes.NewReader(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+apiKey)
|
||||
|
||||
// MiniMax M2.5 reasons before generating — needs generous timeout
|
||||
// pricing (8KB) = 40s, landing (16KB) ~80s, faq (51KB) ~200s
|
||||
timeout := time.Duration(len(user)/80+60) * time.Second
|
||||
if timeout < 3*time.Minute {
|
||||
timeout = 3 * time.Minute
|
||||
}
|
||||
t0 := time.Now()
|
||||
resp, err := (&http.Client{Timeout: timeout}).Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("[%.0fs] %v", time.Since(t0).Seconds(), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respData, _ := io.ReadAll(resp.Body)
|
||||
fmt.Printf("[%.0fs %dKB] ", time.Since(t0).Seconds(), len(respData)/1024)
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return "", fmt.Errorf("HTTP %d: %.300s", resp.StatusCode, respData)
|
||||
}
|
||||
|
||||
var r struct {
|
||||
Choices []struct {
|
||||
Message struct {
|
||||
Content string `json:"content"`
|
||||
Reasoning string `json:"reasoning"`
|
||||
} `json:"message"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
} `json:"choices"`
|
||||
Error *struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(respData, &r); err != nil {
|
||||
return "", fmt.Errorf("bad JSON: %.300s", respData)
|
||||
}
|
||||
if r.Error != nil {
|
||||
return "", fmt.Errorf("API: %s", r.Error.Message)
|
||||
}
|
||||
if len(r.Choices) == 0 {
|
||||
return "", fmt.Errorf("no choices: %.300s", respData)
|
||||
}
|
||||
|
||||
content := r.Choices[0].Message.Content
|
||||
if content == "" {
|
||||
content = r.Choices[0].Message.Reasoning
|
||||
}
|
||||
if content == "" {
|
||||
return "", fmt.Errorf("empty content: %.500s", respData)
|
||||
}
|
||||
if r.Choices[0].FinishReason == "length" {
|
||||
return "", fmt.Errorf("truncated (output hit max_tokens)")
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// --- Review ---
|
||||
|
||||
type fix struct {
|
||||
Old string `json:"old"`
|
||||
New string `json:"new"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
func reviewContent(content, ln, kind string) string {
|
||||
prompt := fmt.Sprintf(`Review this %s translation to %s. Check: wrong words, grammar, broken HTML tags, broken Go template tags, stray whitespace.
|
||||
Return JSON array: [{"old":"exact string","new":"fix","reason":"why"}]. If perfect return [].`, ln, kind)
|
||||
result, err := callLLM(reviewModel, prompt, content, 16384)
|
||||
if err != nil {
|
||||
fmt.Printf("(review error: %v) ", err)
|
||||
return content
|
||||
}
|
||||
fixes := parseFixes(result)
|
||||
applied := 0
|
||||
for _, f := range fixes {
|
||||
if f.Old != "" && f.New != "" && strings.Contains(content, f.Old) {
|
||||
content = strings.Replace(content, f.Old, f.New, 1)
|
||||
applied++
|
||||
}
|
||||
}
|
||||
if applied > 0 {
|
||||
fmt.Printf("(%d fixes) ", applied)
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
func reviewYAML_(english, translated map[string]string, ln string) {
|
||||
type pair struct {
|
||||
EN string `json:"en"`
|
||||
TR string `json:"tr"`
|
||||
}
|
||||
combined := make(map[string]pair)
|
||||
for k, v := range english {
|
||||
combined[k] = pair{EN: v, TR: translated[k]}
|
||||
}
|
||||
data, _ := json.Marshal(combined)
|
||||
|
||||
prompt := fmt.Sprintf(`Review these %s UI string translations. "en" is original, "tr" is translation.
|
||||
Check: wrong translations, grammar, broken format placeholders.
|
||||
Return JSON: [{"old":"yaml_key","new":"corrected value","reason":"why"}]. If perfect return [].`, ln)
|
||||
|
||||
result, err := callLLM(reviewModel, prompt, string(data), 16384)
|
||||
if err != nil {
|
||||
fmt.Printf("(review error: %v) ", err)
|
||||
return
|
||||
}
|
||||
fixes := parseFixes(result)
|
||||
for _, f := range fixes {
|
||||
if _, ok := translated[f.Old]; ok {
|
||||
translated[f.Old] = f.New
|
||||
}
|
||||
}
|
||||
if len(fixes) > 0 {
|
||||
fmt.Printf("(%d fixes) ", len(fixes))
|
||||
}
|
||||
}
|
||||
|
||||
func parseFixes(raw string) []fix {
|
||||
raw = stripFences(strings.TrimSpace(raw))
|
||||
var fixes []fix
|
||||
if json.Unmarshal([]byte(raw), &fixes) != nil {
|
||||
if s := strings.Index(raw, "["); s >= 0 {
|
||||
if e := strings.LastIndex(raw, "]"); e > s {
|
||||
json.Unmarshal([]byte(raw[s:e+1]), &fixes)
|
||||
}
|
||||
}
|
||||
}
|
||||
return fixes
|
||||
}
|
||||
|
||||
// --- Helpers ---
|
||||
|
||||
func ensureDefine(content, name, lang string) string {
|
||||
want := fmt.Sprintf(`{{define "%s_%s"}}`, name, lang)
|
||||
if strings.Contains(content, want) {
|
||||
return content
|
||||
}
|
||||
if i := strings.Index(content, `{{define "`); i >= 0 {
|
||||
if j := strings.Index(content[i:], `"}}`); j > 0 {
|
||||
return content[:i] + want + content[i+j+3:]
|
||||
}
|
||||
}
|
||||
return want + "\n" + content
|
||||
}
|
||||
|
||||
func extractKeys(src string) map[string]string {
|
||||
keys := make(map[string]string)
|
||||
scanner := bufio.NewScanner(strings.NewReader(src))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if t := strings.TrimSpace(line); strings.HasPrefix(t, "#") || t == "" {
|
||||
continue
|
||||
}
|
||||
if idx := strings.Index(line, ":"); idx > 0 {
|
||||
k := strings.TrimSpace(line[:idx])
|
||||
v := strings.TrimSpace(line[idx+1:])
|
||||
if len(v) >= 2 && v[0] == '"' && v[len(v)-1] == '"' {
|
||||
v = v[1 : len(v)-1]
|
||||
}
|
||||
if k != "" && v != "" {
|
||||
keys[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func rebuildYAML(src string, translated map[string]string) string {
|
||||
var out strings.Builder
|
||||
scanner := bufio.NewScanner(strings.NewReader(src))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
t := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(t, "#") || t == "" {
|
||||
out.WriteString(line + "\n")
|
||||
continue
|
||||
}
|
||||
idx := strings.Index(line, ":")
|
||||
if idx < 0 {
|
||||
out.WriteString(line + "\n")
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(line[:idx])
|
||||
if val, ok := translated[key]; ok {
|
||||
if needsQuote(val) {
|
||||
val = strings.ReplaceAll(val, `\`, `\\`)
|
||||
val = strings.ReplaceAll(val, `"`, `\"`)
|
||||
out.WriteString(key + ": \"" + val + "\"\n")
|
||||
} else {
|
||||
out.WriteString(key + ": " + val + "\n")
|
||||
}
|
||||
} else {
|
||||
out.WriteString(line + "\n")
|
||||
}
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func needsQuote(s string) bool {
|
||||
return s == "" || strings.ContainsAny(s, `:{}[]&*?|>!%@`+"`\"'#") ||
|
||||
s[0] == ' ' || s[len(s)-1] == ' ' || s[0] == '-' || s[0] == '{' ||
|
||||
s == "true" || s == "false" || s == "null" || s == "yes" || s == "no"
|
||||
}
|
||||
|
||||
func stripFences(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
for _, p := range []string{"```json", "```yaml", "```html", "```"} {
|
||||
if strings.HasPrefix(s, p) {
|
||||
s = s[len(p):]
|
||||
break
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(s, "```") {
|
||||
s = s[:len(s)-3]
|
||||
}
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
func envKey(name string) string {
|
||||
for _, p := range []string{"anthropic.env", "/tank/inou/anthropic.env"} {
|
||||
if data, err := os.ReadFile(p); err == nil {
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), name+"=") {
|
||||
return strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(line), name+"="))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func findPortalDir() string {
|
||||
dir, _ := os.Getwd()
|
||||
for {
|
||||
if _, err := os.Stat(filepath.Join(dir, "portal", "templates")); err == nil {
|
||||
return filepath.Join(dir, "portal")
|
||||
}
|
||||
p := filepath.Dir(dir)
|
||||
if p == dir {
|
||||
break
|
||||
}
|
||||
dir = p
|
||||
}
|
||||
die("cannot find portal/")
|
||||
return ""
|
||||
}
|
||||
|
||||
func resolveLangs(spec string) []string {
|
||||
if spec == "all" {
|
||||
var out []string
|
||||
for l := range langName {
|
||||
out = append(out, l)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
return strings.Split(spec, ",")
|
||||
}
|
||||
|
||||
func resolveWhat(spec string) ([]string, bool) {
|
||||
if spec == "all" {
|
||||
return knownTemplates, true
|
||||
}
|
||||
var t []string
|
||||
yaml := false
|
||||
for _, p := range strings.Split(spec, ",") {
|
||||
if p == "yaml" {
|
||||
yaml = true
|
||||
} else {
|
||||
t = append(t, p)
|
||||
}
|
||||
}
|
||||
return t, yaml
|
||||
}
|
||||
|
||||
func pick(ss ...string) string {
|
||||
for _, s := range ss {
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func b2i(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func die(msg string) {
|
||||
fmt.Fprintln(os.Stderr, msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
Loading…
Reference in New Issue