From d1b6b5bf898d3e14c23adaeb1fe257a9ae74dab1 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Thu, 5 Nov 2026 11:36:39 +0700 Subject: [PATCH 1/3] feat(linux): add the first beta to the website --- app/Http/Controllers/LinuxController.php | 25 ++++ app/Http/Controllers/LlmsTxtController.php | 1 + app/Services/Content/SiteFacts.php | 25 ++++ app/Services/Releases/PlatformCatalog.php | 8 +- app/Support/Seo/StaticPages.php | 3 +- resources/data/content/de/download.json | 5 + resources/data/content/de/faq.json | 4 +- resources/data/content/de/home.json | 5 +- resources/data/content/de/linux.json | 31 ++++ resources/data/content/de/pricing.json | 3 +- resources/data/content/en/download.json | 5 + resources/data/content/en/faq.json | 4 +- resources/data/content/en/home.json | 5 +- resources/data/content/en/linux.json | 31 ++++ resources/data/content/en/pricing.json | 3 +- resources/data/content/es/download.json | 5 + resources/data/content/es/faq.json | 4 +- resources/data/content/es/home.json | 5 +- resources/data/content/es/linux.json | 31 ++++ resources/data/content/es/pricing.json | 3 +- resources/data/content/fr/download.json | 5 + resources/data/content/fr/faq.json | 4 +- resources/data/content/fr/home.json | 5 +- resources/data/content/fr/linux.json | 31 ++++ resources/data/content/fr/pricing.json | 3 +- resources/data/content/id/download.json | 5 + resources/data/content/id/faq.json | 4 +- resources/data/content/id/home.json | 5 +- resources/data/content/id/linux.json | 31 ++++ resources/data/content/id/pricing.json | 3 +- resources/data/content/it/download.json | 5 + resources/data/content/it/faq.json | 4 +- resources/data/content/it/home.json | 5 +- resources/data/content/it/linux.json | 31 ++++ resources/data/content/it/pricing.json | 3 +- resources/data/content/ja/download.json | 5 + resources/data/content/ja/faq.json | 4 +- resources/data/content/ja/home.json | 5 +- resources/data/content/ja/linux.json | 31 ++++ resources/data/content/ja/pricing.json | 3 +- resources/data/content/ko/download.json | 5 + resources/data/content/ko/faq.json | 4 +- resources/data/content/ko/home.json | 5 +- resources/data/content/ko/linux.json | 31 ++++ resources/data/content/ko/pricing.json | 3 +- resources/data/content/pt-BR/download.json | 5 + resources/data/content/pt-BR/faq.json | 4 +- resources/data/content/pt-BR/home.json | 5 +- resources/data/content/pt-BR/linux.json | 31 ++++ resources/data/content/pt-BR/pricing.json | 3 +- resources/data/content/vi/download.json | 5 + resources/data/content/vi/faq.json | 4 +- resources/data/content/vi/home.json | 5 +- resources/data/content/vi/linux.json | 31 ++++ resources/data/content/vi/pricing.json | 3 +- resources/data/content/zh-Hans/download.json | 5 + resources/data/content/zh-Hans/faq.json | 4 +- resources/data/content/zh-Hans/home.json | 5 +- resources/data/content/zh-Hans/linux.json | 31 ++++ resources/data/content/zh-Hans/pricing.json | 3 +- resources/data/content/zh-Hant/download.json | 5 + resources/data/content/zh-Hant/faq.json | 4 +- resources/data/content/zh-Hant/home.json | 5 +- resources/data/content/zh-Hant/linux.json | 31 ++++ resources/data/content/zh-Hant/pricing.json | 3 +- resources/data/platforms.json | 32 +++- .../js/components/download/command-block.tsx | 21 +-- resources/js/components/home/hero.tsx | 20 +-- .../js/components/home/platforms-section.tsx | 27 +++- resources/js/components/site/site-links.ts | 13 +- resources/js/i18n/messages/de/platforms.ts | 1 + resources/js/i18n/messages/en/platforms.ts | 1 + resources/js/i18n/messages/es/platforms.ts | 1 + resources/js/i18n/messages/fr/platforms.ts | 1 + resources/js/i18n/messages/id/platforms.ts | 1 + resources/js/i18n/messages/it/platforms.ts | 1 + resources/js/i18n/messages/ja/platforms.ts | 1 + resources/js/i18n/messages/ko/platforms.ts | 1 + resources/js/i18n/messages/pt-BR/platforms.ts | 1 + resources/js/i18n/messages/vi/platforms.ts | 1 + .../js/i18n/messages/zh-Hans/platforms.ts | 1 + .../js/i18n/messages/zh-Hant/platforms.ts | 1 + resources/js/lib/data/platforms.ts | 68 ++++++++- resources/js/pages/Download.tsx | 13 +- resources/js/pages/Linux.tsx | 138 ++++++++++++++++++ resources/js/pages/Pricing.tsx | 1 + routes/localized.php | 4 +- .../Feature/Content/PositioningGuardsTest.php | 2 +- tests/Feature/Data/PlatformsDataTest.php | 11 +- tests/Feature/Landing/FaqPageTest.php | 4 +- tests/Feature/Landing/HomepageRenderTest.php | 13 +- tests/Feature/Landing/LandingTest.php | 1 + 92 files changed, 909 insertions(+), 109 deletions(-) create mode 100644 app/Http/Controllers/LinuxController.php create mode 100644 resources/data/content/de/linux.json create mode 100644 resources/data/content/en/linux.json create mode 100644 resources/data/content/es/linux.json create mode 100644 resources/data/content/fr/linux.json create mode 100644 resources/data/content/id/linux.json create mode 100644 resources/data/content/it/linux.json create mode 100644 resources/data/content/ja/linux.json create mode 100644 resources/data/content/ko/linux.json create mode 100644 resources/data/content/pt-BR/linux.json create mode 100644 resources/data/content/vi/linux.json create mode 100644 resources/data/content/zh-Hans/linux.json create mode 100644 resources/data/content/zh-Hant/linux.json create mode 100644 resources/js/pages/Linux.tsx diff --git a/app/Http/Controllers/LinuxController.php b/app/Http/Controllers/LinuxController.php new file mode 100644 index 00000000..49dd9bd2 --- /dev/null +++ b/app/Http/Controllers/LinuxController.php @@ -0,0 +1,25 @@ +find('linux')['linuxEngines'] ?? []; + + return Inertia::render('Linux', [ + 'content' => $content->page('linux', App::getLocale()), + 'engines' => $platforms->isAvailable('linux') && is_array($engines) ? $facts->engineLinks(array_values(array_filter($engines, 'is_string'))) : [], + 'links' => $facts->links(), + 'organizationProfiles' => $facts->organizationProfiles(), + ]); + } +} diff --git a/app/Http/Controllers/LlmsTxtController.php b/app/Http/Controllers/LlmsTxtController.php index 05482dd4..e31c6454 100644 --- a/app/Http/Controllers/LlmsTxtController.php +++ b/app/Http/Controllers/LlmsTxtController.php @@ -33,6 +33,7 @@ class LlmsTxtController extends Controller 'landing.teams', 'landing.download', 'landing.ios', + 'landing.linux', 'landing.integrations.index', 'landing.faq', 'landing.security', diff --git a/app/Services/Content/SiteFacts.php b/app/Services/Content/SiteFacts.php index 7322d028..9da06512 100644 --- a/app/Services/Content/SiteFacts.php +++ b/app/Services/Content/SiteFacts.php @@ -162,6 +162,31 @@ public function iosEngines(array $pickerOrder): array return ['picker' => $picker, 'syncedOnly' => $syncedOnly]; } + /** + * @param list $ids + * @return list + */ + public function engineLinks(array $ids): array + { + $byId = []; + + foreach ($this->engines() as $engine) { + if (is_string($engine['id'] ?? null)) { + $byId[$engine['id']] = $engine; + } + } + + $links = []; + + foreach ($ids as $id) { + if (($byId[$id]['state'] ?? null) === 'published') { + $links[] = $this->engineLink($byId[$id], $byId); + } + } + + return $links; + } + /** * @return list */ diff --git a/app/Services/Releases/PlatformCatalog.php b/app/Services/Releases/PlatformCatalog.php index cfe3647c..90a0dffc 100644 --- a/app/Services/Releases/PlatformCatalog.php +++ b/app/Services/Releases/PlatformCatalog.php @@ -87,6 +87,12 @@ public function isReleased(string $id): bool return ($this->find($id)['status'] ?? null) === 'released'; } + /** A beta has installable packages even though it is not a stable release. */ + public function isAvailable(string $id): bool + { + return in_array($this->find($id)['status'] ?? null, ['released', 'beta'], true); + } + /** * The ids of the platforms with nothing to install, in data order. * @@ -97,7 +103,7 @@ public function unreleased(): array $ids = []; foreach ($this->all() as $platform) { - if (($platform['status'] ?? null) !== 'released' && is_string($platform['id'] ?? null)) { + if (! in_array($platform['status'] ?? null, ['released', 'beta'], true) && is_string($platform['id'] ?? null)) { $ids[] = $platform['id']; } } diff --git a/app/Support/Seo/StaticPages.php b/app/Support/Seo/StaticPages.php index 59ea1c00..6e9476fe 100644 --- a/app/Support/Seo/StaticPages.php +++ b/app/Support/Seo/StaticPages.php @@ -8,7 +8,7 @@ use App\Support\Pricing\Campaign; /** - * The one-off pages: home, download, iOS, pricing, teams, FAQ, about, security, sponsors, the dated sale and the blog index. + * The one-off pages: home, download, iOS, Linux, pricing, teams, FAQ, about, security, sponsors, the dated sale and the blog index. * * Each renders in a locale when `resources/data/content/{locale}/{page}.json` * exists, and is indexable there unless that file sets `seo.indexable` to @@ -27,6 +27,7 @@ final class StaticPages implements PageFamily 'landing.home' => 'home', 'landing.download' => 'download', 'landing.ios' => 'ios', + 'landing.linux' => 'linux', 'landing.pricing' => 'pricing', 'landing.teams' => 'teams', 'landing.faq' => 'faq', diff --git a/resources/data/content/de/download.json b/resources/data/content/de/download.json index dfbf1330..de76a8fb 100644 --- a/resources/data/content/de/download.json +++ b/resources/data/content/de/download.json @@ -59,5 +59,10 @@ "body": "Jede Version mit ihren Hinweisen und Disk-Images findest du auf GitHub Releases. Das Änderungsprotokoll listet die Änderungen jeder Version auf.", "releases": "Alle Versionen auf GitHub", "changelog": "Änderungsprotokoll (Englisch)" + }, + "linux": { + "title": "TablePro für Linux", + "body": "Eine Linux-Beta mit SQL-Editor und Datentabelle.", + "link": "Linux-Installationsanleitung lesen" } } diff --git a/resources/data/content/de/faq.json b/resources/data/content/de/faq.json index 292e9a5a..954ebff5 100644 --- a/resources/data/content/de/faq.json +++ b/resources/data/content/de/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Gibt es eine Version für Windows oder Linux?", + "question": "Gibt es eine Linux-Version?", "answer": [ - "Nein. Es gibt keine Windows-Version. Ein Linux-Prototyp existiert, aber es gibt nichts zum Installieren und keinen Erscheinungstermin." + "Die Linux-App ist als Beta verfügbar. Pakete und Anleitungen findest du auf der Downloadseite." ] }, { diff --git a/resources/data/content/de/home.json b/resources/data/content/de/home.json index 2855c1fa..6b8c2609 100644 --- a/resources/data/content/de/home.json +++ b/resources/data/content/de/home.json @@ -9,7 +9,7 @@ "title": "Ein nativer Datenbankclient." }, "hero": { - "title": "Ein nativer Datenbankclient.", + "title": "Ein nativer Datenbankclient für {devices}.", "subtitle": "Führe Abfragen aus, durchsuche und bearbeite Daten in {featuredEngines} und weiteren Systemen.", "native": "Native Oberflächen statt Electron oder Java-Laufzeitumgebung.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro für {devices}", "mac": "Die Desktop-App mit separaten Builds für {architectures}. Mit SQL-Editor, Schemawerkzeugen, KI-Assistent und MCP-Server.", "ios": "Führe Abfragen aus und arbeite mit unterstützten Tabellen auf {devices}. Eine separate kostenlose App mit SSH-Tunneln und optionaler Face-ID-Sperre.", - "sync": "iCloud Sync teilt Verbindungen, Gruppen und Tags zwischen Apple-Geräten. Standardmäßig aus; auf dem Mac ist {tier} erforderlich." + "sync": "iCloud Sync teilt Verbindungen, Gruppen und Tags zwischen Apple-Geräten. Standardmäßig aus; auf dem Mac ist {tier} erforderlich.", + "linux": "Eine Linux-Beta mit SQL-Editor und Datentabelle." }, "switch": { "title": "Deine Verbindungen übernehmen", diff --git a/resources/data/content/de/linux.json b/resources/data/content/de/linux.json new file mode 100644 index 00000000..a8a1b51b --- /dev/null +++ b/resources/data/content/de/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro für Linux", + "description": "Eine Linux-Beta mit SQL-Editor und Datentabelle." + }, + "hero": { + "title": "TablePro für Linux", + "lead": "Eine Linux-Beta mit SQL-Editor und Datentabelle." + }, + "install": { + "title": "Beta installieren", + "label": "Befehle für {system}", + "lead": "Pakete für {architectures}. Aktiviere das stabile und das Beta-Repository, um Updates über apt oder dnf zu erhalten.", + "stable": { + "title": "Stabile Versionen", + "body": "Aktiviere nur das stabile Repository, wenn du nur stabile Versionen möchtest. Beta-Tags veröffentlichen nur in den Beta-Repositories; stabile Tags nur in den stabilen." + }, + "releases": { + "title": "Pakete auf GitHub", + "body": "Lade .deb-, .rpm- und .flatpak-Dateien von GitHub Releases herunter. Installiere die nächste Datei zum Aktualisieren." + }, + "guide": { + "label": "Linux-Installationsanleitung lesen", + "path": "/linux/install" + } + }, + "databases": { + "title": "Datenbanken", + "lead": "Diese Treiber sind in der Linux-App enthalten." + } +} diff --git a/resources/data/content/de/pricing.json b/resources/data/content/de/pricing.json index fac910ad..eec34e81 100644 --- a/resources/data/content/de/pricing.json +++ b/resources/data/content/de/pricing.json @@ -50,7 +50,8 @@ "summary": "Was mit jeder Bezahlfunktion nach Tarifende passiert", "intro": "Jede Bezahlfunktion wird auf eigene Weise deaktiviert:" }, - "terms": "Die Nutzungsbedingungen legen fest, was eine Lizenz erlaubt." + "terms": "Die Nutzungsbedingungen legen fest, was eine Lizenz erlaubt.", + "linux": "Für Linux gilt dasselbe Lizenzmodell wie für den Mac. Die kostenpflichtigen Funktionen auf der Preisseite sind vorerst nur auf dem Mac verfügbar und kommen später für Linux." }, "billing": { "title": "Abrechnung", diff --git a/resources/data/content/en/download.json b/resources/data/content/en/download.json index e23f265c..120718d6 100644 --- a/resources/data/content/en/download.json +++ b/resources/data/content/en/download.json @@ -59,5 +59,10 @@ "body": "Every release, with its notes and disk images, is on GitHub Releases. The changelog lists what changed in each version.", "releases": "All releases on GitHub", "changelog": "Changelog" + }, + "linux": { + "title": "TablePro for Linux", + "body": "A Linux beta with a SQL editor and data grid.", + "link": "Read the Linux install guide" } } diff --git a/resources/data/content/en/faq.json b/resources/data/content/en/faq.json index f564ecfe..3431b5b9 100644 --- a/resources/data/content/en/faq.json +++ b/resources/data/content/en/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Is there a version for Windows or Linux?", + "question": "Is there a Linux version?", "answer": [ - "No. There is no Windows version. A Linux prototype exists, but there is nothing to install and no release date." + "The Linux app is in beta. See the download page for packages and installation instructions." ] }, { diff --git a/resources/data/content/en/home.json b/resources/data/content/en/home.json index 8d9bbbc4..1910de1a 100644 --- a/resources/data/content/en/home.json +++ b/resources/data/content/en/home.json @@ -9,7 +9,7 @@ "title": "A native database client." }, "hero": { - "title": "A native database client.", + "title": "A native database client for {devices}.", "subtitle": "Run queries, browse and edit data in {featuredEngines} and more.", "native": "Built with native interfaces, not Electron or a Java runtime.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro for {devices}", "mac": "The desktop app, with separate builds for {architectures}. Includes the SQL editor, schema tools, AI assistant and MCP server.", "ios": "Run queries and work with supported tables on {devices}. A separate, free app with SSH tunnels and an optional Face ID lock.", - "sync": "iCloud Sync shares connections, groups and tags across Apple devices. It is off by default and requires {tier} on the Mac." + "sync": "iCloud Sync shares connections, groups and tags across Apple devices. It is off by default and requires {tier} on the Mac.", + "linux": "A Linux beta with a SQL editor and data grid." }, "switch": { "title": "Bring your connections", diff --git a/resources/data/content/en/linux.json b/resources/data/content/en/linux.json new file mode 100644 index 00000000..36bc086a --- /dev/null +++ b/resources/data/content/en/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro for Linux", + "description": "A Linux beta with a SQL editor and data grid." + }, + "hero": { + "title": "TablePro for Linux", + "lead": "A Linux beta with a SQL editor and data grid." + }, + "install": { + "title": "Install the beta", + "label": "Commands for {system}", + "lead": "Packages for {architectures}. Enable both the stable and beta repositories to receive updates through apt or dnf.", + "stable": { + "title": "Stable releases", + "body": "For stable releases only, enable the stable repository. Beta tags publish only to the beta repositories; stable tags publish only to the stable ones." + }, + "releases": { + "title": "Packages on GitHub", + "body": "Get .deb, .rpm and .flatpak files from GitHub Releases. Install the next file to update." + }, + "guide": { + "label": "Read the Linux install guide", + "path": "/linux/install" + } + }, + "databases": { + "title": "Databases", + "lead": "These drivers are included in the Linux app." + } +} diff --git a/resources/data/content/en/pricing.json b/resources/data/content/en/pricing.json index a1699e44..91c6ec6c 100644 --- a/resources/data/content/en/pricing.json +++ b/resources/data/content/en/pricing.json @@ -50,7 +50,8 @@ "summary": "What each paid feature does when a plan ends", "intro": "Each paid feature stops in its own way:" }, - "terms": "The terms of service set out what a license allows." + "terms": "The terms of service set out what a license allows.", + "linux": "Linux follows the same licensing model as the Mac. The paid features listed on the Pricing page are Mac-only for now and come to Linux later." }, "billing": { "title": "Billing", diff --git a/resources/data/content/es/download.json b/resources/data/content/es/download.json index 249d6c44..2d641304 100644 --- a/resources/data/content/es/download.json +++ b/resources/data/content/es/download.json @@ -59,5 +59,10 @@ "body": "Todas las versiones, con sus notas e imágenes de disco, están en GitHub Releases. El historial de cambios enumera las novedades de cada versión.", "releases": "Todas las versiones en GitHub", "changelog": "Historial de cambios (inglés)" + }, + "linux": { + "title": "TablePro para Linux", + "body": "Una beta para Linux con editor SQL y cuadrícula de datos.", + "link": "Leer la guía de instalación en Linux" } } diff --git a/resources/data/content/es/faq.json b/resources/data/content/es/faq.json index 96d8468e..6c620ed0 100644 --- a/resources/data/content/es/faq.json +++ b/resources/data/content/es/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "¿Hay una versión para Windows o Linux?", + "question": "¿Hay una versión para Linux?", "answer": [ - "No. No hay versión para Windows. Existe un prototipo para Linux, pero no hay nada que instalar ni fecha de lanzamiento." + "La aplicación para Linux está en beta. Consulta los paquetes y las instrucciones en la página de descargas." ] }, { diff --git a/resources/data/content/es/home.json b/resources/data/content/es/home.json index e311239e..5401f39d 100644 --- a/resources/data/content/es/home.json +++ b/resources/data/content/es/home.json @@ -9,7 +9,7 @@ "title": "Un cliente nativo de bases de datos." }, "hero": { - "title": "Un cliente nativo de bases de datos.", + "title": "Un cliente de bases de datos nativo para {devices}.", "subtitle": "Ejecuta consultas, explora y edita datos en {featuredEngines} y más.", "native": "Interfaces nativas, sin Electron ni entorno Java.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro para {devices}", "mac": "La app de escritorio, con versiones independientes para {architectures}. Incluye editor SQL, herramientas de esquemas, asistente de IA y servidor MCP.", "ios": "Ejecuta consultas y trabaja con tablas compatibles en {devices}. Una app gratuita e independiente, con túneles SSH y bloqueo opcional con Face ID.", - "sync": "iCloud Sync comparte conexiones, grupos y etiquetas entre dispositivos Apple. Está desactivado por defecto y requiere {tier} en el Mac." + "sync": "iCloud Sync comparte conexiones, grupos y etiquetas entre dispositivos Apple. Está desactivado por defecto y requiere {tier} en el Mac.", + "linux": "Una beta para Linux con editor SQL y cuadrícula de datos." }, "switch": { "title": "Trae tus conexiones", diff --git a/resources/data/content/es/linux.json b/resources/data/content/es/linux.json new file mode 100644 index 00000000..834d6d75 --- /dev/null +++ b/resources/data/content/es/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro para Linux", + "description": "Una beta para Linux con editor SQL y cuadrícula de datos." + }, + "hero": { + "title": "TablePro para Linux", + "lead": "Una beta para Linux con editor SQL y cuadrícula de datos." + }, + "install": { + "title": "Instalar la beta", + "label": "Comandos para {system}", + "lead": "Paquetes para {architectures}. Activa los repositorios estable y beta para recibir actualizaciones mediante apt o dnf.", + "stable": { + "title": "Versiones estables", + "body": "Para recibir solo versiones estables, activa el repositorio estable. Las etiquetas beta publican solo en los repositorios beta; las estables, solo en los estables." + }, + "releases": { + "title": "Paquetes en GitHub", + "body": "Descarga archivos .deb, .rpm y .flatpak de GitHub Releases. Instala el siguiente archivo para actualizar." + }, + "guide": { + "label": "Leer la guía de instalación en Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Bases de datos", + "lead": "Estos controladores están incluidos en la aplicación para Linux." + } +} diff --git a/resources/data/content/es/pricing.json b/resources/data/content/es/pricing.json index a0e29a39..9ec8eb7c 100644 --- a/resources/data/content/es/pricing.json +++ b/resources/data/content/es/pricing.json @@ -50,7 +50,8 @@ "summary": "Qué ocurre con cada función de pago al terminar un plan", "intro": "Cada función de pago se detiene de una forma distinta:" }, - "terms": "Las condiciones del servicio especifican qué permite una licencia." + "terms": "Las condiciones del servicio especifican qué permite una licencia.", + "linux": "Linux sigue el mismo modelo de licencias que Mac. Las funciones de pago de la página de precios están disponibles solo en Mac por ahora y llegarán a Linux más adelante." }, "billing": { "title": "Facturación", diff --git a/resources/data/content/fr/download.json b/resources/data/content/fr/download.json index d9cf9cfa..9b267241 100644 --- a/resources/data/content/fr/download.json +++ b/resources/data/content/fr/download.json @@ -59,5 +59,10 @@ "body": "Chaque version, avec ses notes et ses images disque, figure sur GitHub Releases. Le journal des modifications liste les changements de chaque version.", "releases": "Toutes les versions sur GitHub", "changelog": "Journal des modifications (anglais)" + }, + "linux": { + "title": "TablePro pour Linux", + "body": "Une bêta Linux avec un éditeur SQL et une grille de données.", + "link": "Lire le guide d’installation Linux" } } diff --git a/resources/data/content/fr/faq.json b/resources/data/content/fr/faq.json index 4641466c..da1fadc0 100644 --- a/resources/data/content/fr/faq.json +++ b/resources/data/content/fr/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Existe-t-il une version Windows ou Linux ?", + "question": "Existe-t-il une version Linux ?", "answer": [ - "Non. Il n’y a aucune version Windows. Un prototype Linux existe, mais il n’y a rien à installer et aucune date de sortie." + "L’application Linux est en bêta. Consultez les paquets et les instructions sur la page de téléchargement." ] }, { diff --git a/resources/data/content/fr/home.json b/resources/data/content/fr/home.json index 429e6ff9..a60e0646 100644 --- a/resources/data/content/fr/home.json +++ b/resources/data/content/fr/home.json @@ -9,7 +9,7 @@ "title": "Un client natif de bases de données." }, "hero": { - "title": "Un client natif de bases de données.", + "title": "Un client de bases de données natif pour {devices}.", "subtitle": "Exécutez des requêtes, parcourez et modifiez les données dans {featuredEngines} et d’autres moteurs.", "native": "Des interfaces natives, sans Electron ni environnement Java.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro pour {devices}", "mac": "L’app de bureau, avec des versions distinctes pour {architectures}. Elle inclut l’éditeur SQL, les outils de schéma, l’assistant IA et le serveur MCP.", "ios": "Exécutez des requêtes et travaillez avec les tables compatibles sur {devices}. Une app gratuite distincte, avec tunnels SSH et verrouillage Face ID optionnel.", - "sync": "iCloud Sync partage connexions, groupes et tags entre appareils Apple. Désactivé par défaut, il nécessite {tier} sur Mac." + "sync": "iCloud Sync partage connexions, groupes et tags entre appareils Apple. Désactivé par défaut, il nécessite {tier} sur Mac.", + "linux": "Une bêta Linux avec un éditeur SQL et une grille de données." }, "switch": { "title": "Importez vos connexions", diff --git a/resources/data/content/fr/linux.json b/resources/data/content/fr/linux.json new file mode 100644 index 00000000..89bc202a --- /dev/null +++ b/resources/data/content/fr/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro pour Linux", + "description": "Une bêta Linux avec un éditeur SQL et une grille de données." + }, + "hero": { + "title": "TablePro pour Linux", + "lead": "Une bêta Linux avec un éditeur SQL et une grille de données." + }, + "install": { + "title": "Installer la bêta", + "label": "Commandes pour {system}", + "lead": "Paquets pour {architectures}. Activez les dépôts stable et bêta pour recevoir les mises à jour via apt ou dnf.", + "stable": { + "title": "Versions stables", + "body": "Pour recevoir uniquement les versions stables, activez le dépôt stable. Les tags bêta publient uniquement dans les dépôts bêta ; les tags stables, uniquement dans les dépôts stables." + }, + "releases": { + "title": "Paquets sur GitHub", + "body": "Téléchargez les fichiers .deb, .rpm et .flatpak sur GitHub Releases. Installez le fichier suivant pour mettre à jour." + }, + "guide": { + "label": "Lire le guide d’installation Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Bases de données", + "lead": "Ces pilotes sont inclus dans l’application Linux." + } +} diff --git a/resources/data/content/fr/pricing.json b/resources/data/content/fr/pricing.json index 132863bb..8c91ec5e 100644 --- a/resources/data/content/fr/pricing.json +++ b/resources/data/content/fr/pricing.json @@ -50,7 +50,8 @@ "summary": "Ce que devient chaque fonctionnalité payante à la fin d’une offre", "intro": "Chaque fonctionnalité payante s’arrête à sa manière :" }, - "terms": "Les conditions d’utilisation précisent ce qu’autorise une licence." + "terms": "Les conditions d’utilisation précisent ce qu’autorise une licence.", + "linux": "Linux suit le même modèle de licence que le Mac. Les fonctions payantes de la page Tarifs sont réservées au Mac pour le moment et arriveront sur Linux plus tard." }, "billing": { "title": "Facturation", diff --git a/resources/data/content/id/download.json b/resources/data/content/id/download.json index d6996966..b745d97b 100644 --- a/resources/data/content/id/download.json +++ b/resources/data/content/id/download.json @@ -59,5 +59,10 @@ "body": "Setiap rilis beserta catatan dan disk image-nya tersedia di GitHub Releases. Catatan perubahan mencantumkan perubahan dalam setiap versi.", "releases": "Semua rilis di GitHub", "changelog": "Catatan perubahan (bahasa Inggris)" + }, + "linux": { + "title": "TablePro untuk Linux", + "body": "Versi beta Linux dengan editor SQL dan grid data.", + "link": "Baca panduan instalasi Linux" } } diff --git a/resources/data/content/id/faq.json b/resources/data/content/id/faq.json index 42cb679a..be1ee726 100644 --- a/resources/data/content/id/faq.json +++ b/resources/data/content/id/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Apakah ada versi Windows atau Linux?", + "question": "Apakah ada versi Linux?", "answer": [ - "Tidak. Tidak ada versi Windows. Prototipe Linux ada, tetapi tidak ada yang dapat diinstal dan tidak ada tanggal rilis." + "Aplikasi Linux tersedia dalam versi beta. Lihat paket dan petunjuk instalasi di halaman unduhan." ] }, { diff --git a/resources/data/content/id/home.json b/resources/data/content/id/home.json index c9a7b8a1..4755a77d 100644 --- a/resources/data/content/id/home.json +++ b/resources/data/content/id/home.json @@ -9,7 +9,7 @@ "title": "Klien database native." }, "hero": { - "title": "Klien database native.", + "title": "Klien database native untuk {devices}.", "subtitle": "Jalankan kueri, telusuri dan edit data di {featuredEngines} dan lainnya.", "native": "Antarmuka native, tanpa Electron atau runtime Java.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro untuk {devices}", "mac": "Aplikasi desktop, dengan build terpisah untuk {architectures}. Termasuk editor SQL, alat skema, asisten AI, dan server MCP.", "ios": "Jalankan kueri dan bekerja dengan tabel yang didukung di {devices}. Aplikasi gratis terpisah dengan terowongan SSH dan kunci Face ID opsional.", - "sync": "iCloud Sync berbagi koneksi, grup, dan tag di seluruh perangkat Apple. Ini dinonaktifkan secara default dan memerlukan {tier} di Mac." + "sync": "iCloud Sync berbagi koneksi, grup, dan tag di seluruh perangkat Apple. Ini dinonaktifkan secara default dan memerlukan {tier} di Mac.", + "linux": "Versi beta Linux dengan editor SQL dan grid data." }, "switch": { "title": "Bawa koneksi Anda", diff --git a/resources/data/content/id/linux.json b/resources/data/content/id/linux.json new file mode 100644 index 00000000..43c3e65f --- /dev/null +++ b/resources/data/content/id/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro untuk Linux", + "description": "Versi beta Linux dengan editor SQL dan grid data." + }, + "hero": { + "title": "TablePro untuk Linux", + "lead": "Versi beta Linux dengan editor SQL dan grid data." + }, + "install": { + "title": "Instal versi beta", + "label": "Perintah untuk {system}", + "lead": "Paket untuk {architectures}. Aktifkan repositori stabil dan beta untuk menerima pembaruan melalui apt atau dnf.", + "stable": { + "title": "Rilis stabil", + "body": "Untuk menerima rilis stabil saja, aktifkan repositori stabil. Tag beta hanya diterbitkan ke repositori beta; tag stabil hanya ke repositori stabil." + }, + "releases": { + "title": "Paket di GitHub", + "body": "Unduh file .deb, .rpm, dan .flatpak dari GitHub Releases. Instal file versi berikutnya untuk memperbarui." + }, + "guide": { + "label": "Baca panduan instalasi Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Database", + "lead": "Driver ini disertakan dalam aplikasi Linux." + } +} diff --git a/resources/data/content/id/pricing.json b/resources/data/content/id/pricing.json index fe768308..fb325729 100644 --- a/resources/data/content/id/pricing.json +++ b/resources/data/content/id/pricing.json @@ -50,7 +50,8 @@ "summary": "Perilaku setiap fitur berbayar saat paket berakhir", "intro": "Setiap fitur berbayar berhenti dengan cara tersendiri:" }, - "terms": "Ketentuan layanan menjelaskan apa yang diizinkan oleh lisensi." + "terms": "Ketentuan layanan menjelaskan apa yang diizinkan oleh lisensi.", + "linux": "Linux mengikuti model lisensi yang sama dengan Mac. Fitur berbayar pada halaman Harga saat ini hanya tersedia di Mac dan akan hadir di Linux nanti." }, "billing": { "title": "Penagihan", diff --git a/resources/data/content/it/download.json b/resources/data/content/it/download.json index 72ef8042..52e35f40 100644 --- a/resources/data/content/it/download.json +++ b/resources/data/content/it/download.json @@ -59,5 +59,10 @@ "body": "Ogni rilascio, con le note e le immagini disco, si trova su GitHub Releases. Il registro delle modifiche elenca le novità di ogni versione.", "releases": "Tutti i rilasci su GitHub", "changelog": "Registro delle modifiche (inglese)" + }, + "linux": { + "title": "TablePro per Linux", + "body": "Una beta per Linux con editor SQL e griglia dati.", + "link": "Leggi la guida di installazione Linux" } } diff --git a/resources/data/content/it/faq.json b/resources/data/content/it/faq.json index 8a77ba0d..547163c8 100644 --- a/resources/data/content/it/faq.json +++ b/resources/data/content/it/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Esiste una versione per Windows o Linux?", + "question": "Esiste una versione per Linux?", "answer": [ - "No. Non esiste una versione Windows. Esiste un prototipo Linux, ma non c’è nulla da installare né una data di rilascio." + "L’app Linux è in beta. Consulta i pacchetti e le istruzioni nella pagina di download." ] }, { diff --git a/resources/data/content/it/home.json b/resources/data/content/it/home.json index cb299f16..5061f8ea 100644 --- a/resources/data/content/it/home.json +++ b/resources/data/content/it/home.json @@ -9,7 +9,7 @@ "title": "Un client database nativo." }, "hero": { - "title": "Un client database nativo.", + "title": "Un client database nativo per {devices}.", "subtitle": "Esegui query, esplora e modifica dati in {featuredEngines} e altri database.", "native": "Interfacce native, senza Electron né runtime Java.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro per {devices}", "mac": "L'app desktop, con build separate per {architectures}. Include l'editor SQL, gli strumenti dello schema, l'assistente IA e il server MCP.", "ios": "Esegui query e lavora con le tabelle supportate su {devices}. Un'app separata e gratuita con tunnel SSH e un blocco Face ID opzionale.", - "sync": "iCloud Sync condivide connessioni, gruppi e tag tra i dispositivi Apple. È disattivato per imposto predefinita e richiede {tier} su Mac." + "sync": "iCloud Sync condivide connessioni, gruppi e tag tra i dispositivi Apple. È disattivato per imposto predefinita e richiede {tier} su Mac.", + "linux": "Una beta per Linux con editor SQL e griglia dati." }, "switch": { "title": "Porta le tue connessioni", diff --git a/resources/data/content/it/linux.json b/resources/data/content/it/linux.json new file mode 100644 index 00000000..95aa983a --- /dev/null +++ b/resources/data/content/it/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro per Linux", + "description": "Una beta per Linux con editor SQL e griglia dati." + }, + "hero": { + "title": "TablePro per Linux", + "lead": "Una beta per Linux con editor SQL e griglia dati." + }, + "install": { + "title": "Installa la beta", + "label": "Comandi per {system}", + "lead": "Pacchetti per {architectures}. Abilita i repository stabile e beta per ricevere aggiornamenti tramite apt o dnf.", + "stable": { + "title": "Versioni stabili", + "body": "Per ricevere solo versioni stabili, abilita il repository stabile. I tag beta pubblicano solo nei repository beta; i tag stabili solo in quelli stabili." + }, + "releases": { + "title": "Pacchetti su GitHub", + "body": "Scarica i file .deb, .rpm e .flatpak da GitHub Releases. Installa il file successivo per aggiornare." + }, + "guide": { + "label": "Leggi la guida di installazione Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Database", + "lead": "Questi driver sono inclusi nell’app Linux." + } +} diff --git a/resources/data/content/it/pricing.json b/resources/data/content/it/pricing.json index 1e664473..9f237be6 100644 --- a/resources/data/content/it/pricing.json +++ b/resources/data/content/it/pricing.json @@ -50,7 +50,8 @@ "summary": "Cosa succede a ogni funzionalità a pagamento quando termina un piano", "intro": "Ogni funzionalità a pagamento si interrompe in modo diverso:" }, - "terms": "I termini di servizio definiscono cosa consente una licenza." + "terms": "I termini di servizio definiscono cosa consente una licenza.", + "linux": "Linux segue lo stesso modello di licenza del Mac. Le funzioni a pagamento della pagina Prezzi sono per ora disponibili solo sul Mac e arriveranno su Linux in seguito." }, "billing": { "title": "Fatturazione", diff --git a/resources/data/content/ja/download.json b/resources/data/content/ja/download.json index 2127901d..4e75eb1e 100644 --- a/resources/data/content/ja/download.json +++ b/resources/data/content/ja/download.json @@ -59,5 +59,10 @@ "body": "すべてのリリースのノートとディスクイメージは GitHub Releases にあります。各バージョンの変更内容は変更履歴で確認できます。", "releases": "GitHub の全リリース", "changelog": "変更履歴(英語)" + }, + "linux": { + "title": "Linux 向け TablePro", + "body": "SQL エディターとデータグリッドを備えた Linux ベータ版。", + "link": "Linux インストールガイドを読む" } } diff --git a/resources/data/content/ja/faq.json b/resources/data/content/ja/faq.json index dc8a2609..721458ee 100644 --- a/resources/data/content/ja/faq.json +++ b/resources/data/content/ja/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Windows や Linux 版はありますか?", + "question": "Linux 版はありますか?", "answer": [ - "いいえ。Windows 版はありません。Linux のプロトタイプはありますが、インストールできるものはなく、リリース日の予定もありません。" + "Linux アプリはベータ版です。パッケージとインストール手順は ダウンロードページ をご覧ください。" ] }, { diff --git a/resources/data/content/ja/home.json b/resources/data/content/ja/home.json index 35671b6c..a7ce70d7 100644 --- a/resources/data/content/ja/home.json +++ b/resources/data/content/ja/home.json @@ -9,7 +9,7 @@ "title": "ネイティブのデータベースクライアント。" }, "hero": { - "title": "ネイティブのデータベースクライアント。", + "title": "{devices} 向けのネイティブデータベースクライアント。", "subtitle": "{featuredEngines} などのデータベースでクエリを実行し、データを閲覧・編集できます。", "native": "Electron や Java ランタイムではなく、ネイティブのインターフェースで構築しています。", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "{devices} 版 TablePro", "mac": "{architectures} 向けに別々のビルドを提供するデスクトップアプリです。SQL エディター、スキーマツール、AI アシスタント、MCP サーバーを含みます。", "ios": "{devices} でクエリを実行し、対応テーブルを操作できます。SSH トンネルと任意の Face ID ロックを備えた、別の無料アプリです。", - "sync": "iCloud Sync は Apple デバイス間で接続、グループ、タグを共有します。初期状態では無効で、Mac では {tier} が必要です。" + "sync": "iCloud Sync は Apple デバイス間で接続、グループ、タグを共有します。初期状態では無効で、Mac では {tier} が必要です。", + "linux": "SQL エディターとデータグリッドを備えた Linux ベータ版。" }, "switch": { "title": "接続を移行", diff --git a/resources/data/content/ja/linux.json b/resources/data/content/ja/linux.json new file mode 100644 index 00000000..30336fe4 --- /dev/null +++ b/resources/data/content/ja/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "Linux 向け TablePro", + "description": "SQL エディターとデータグリッドを備えた Linux ベータ版。" + }, + "hero": { + "title": "Linux 向け TablePro", + "lead": "SQL エディターとデータグリッドを備えた Linux ベータ版。" + }, + "install": { + "title": "ベータ版をインストール", + "label": "{system} 用のコマンド", + "lead": "{architectures} 用のパッケージ。安定版とベータ版の両方のリポジトリを有効にすると、apt または dnf で更新できます。", + "stable": { + "title": "安定版", + "body": "安定版のみを使う場合は安定版リポジトリを有効にしてください。ベータ版のタグはベータ版リポジトリに、安定版のタグは安定版リポジトリにのみ公開されます。" + }, + "releases": { + "title": "GitHub のパッケージ", + "body": "GitHub Releases から .deb、.rpm、.flatpak ファイルを取得してください。更新には次のファイルをインストールします。" + }, + "guide": { + "label": "Linux インストールガイドを読む", + "path": "/linux/install" + } + }, + "databases": { + "title": "データベース", + "lead": "これらのドライバーは Linux アプリに含まれています。" + } +} diff --git a/resources/data/content/ja/pricing.json b/resources/data/content/ja/pricing.json index c2e16e7d..d1f0a96e 100644 --- a/resources/data/content/ja/pricing.json +++ b/resources/data/content/ja/pricing.json @@ -50,7 +50,8 @@ "summary": "プラン終了時の各有料機能の動作", "intro": "有料機能はそれぞれ次のように停止します:" }, - "terms": "ライセンスで許可される範囲は利用規約で定めています。" + "terms": "ライセンスで許可される範囲は利用規約で定めています。", + "linux": "Linux は Mac と同じライセンスモデルです。料金ページの有料機能は現在 Mac のみで利用でき、Linux には今後追加されます。" }, "billing": { "title": "お支払い", diff --git a/resources/data/content/ko/download.json b/resources/data/content/ko/download.json index 500089da..8d0aadf3 100644 --- a/resources/data/content/ko/download.json +++ b/resources/data/content/ko/download.json @@ -59,5 +59,10 @@ "body": "모든 릴리스의 노트와 디스크 이미지는 GitHub Releases에 있습니다. 변경 기록에는 각 버전의 변경 사항이 나와 있습니다.", "releases": "GitHub의 모든 릴리스", "changelog": "변경 기록 (영어)" + }, + "linux": { + "title": "Linux용 TablePro", + "body": "SQL 편집기와 데이터 그리드를 갖춘 Linux 베타 버전.", + "link": "Linux 설치 가이드 읽기" } } diff --git a/resources/data/content/ko/faq.json b/resources/data/content/ko/faq.json index 85fd5211..707bbdc4 100644 --- a/resources/data/content/ko/faq.json +++ b/resources/data/content/ko/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Windows 또는 Linux 버전이 있나요?", + "question": "Linux 버전이 있나요?", "answer": [ - "아니요. Windows 버전은 없습니다. Linux 프로토타입은 있지만 설치 가능한 버전과 출시 일정은 없습니다." + "Linux 앱은 베타 버전입니다. 패키지와 설치 방법은 다운로드 페이지를 확인하세요." ] }, { diff --git a/resources/data/content/ko/home.json b/resources/data/content/ko/home.json index 71c548dd..00aeaaaa 100644 --- a/resources/data/content/ko/home.json +++ b/resources/data/content/ko/home.json @@ -9,7 +9,7 @@ "title": "네이티브 데이터베이스 클라이언트." }, "hero": { - "title": "네이티브 데이터베이스 클라이언트.", + "title": "{devices}용 네이티브 데이터베이스 클라이언트.", "subtitle": "{featuredEngines} 등의 데이터베이스에서 쿼리를 실행하고 데이터를 탐색하고 편집하세요.", "native": "Electron이나 Java 런타임 대신 네이티브 인터페이스로 만들었습니다.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "{devices}용 TablePro", "mac": "{architectures}용 빌드를 각각 제공하는 데스크톱 앱입니다. SQL 편집기, 스키마 도구, AI 도우미, MCP 서버가 포함됩니다.", "ios": "{devices}에서 쿼리를 실행하고 지원되는 테이블을 다루세요. SSH 터널과 선택적인 Face ID 잠금을 제공하는 별도의 무료 앱입니다.", - "sync": "iCloud Sync는 Apple 기기 간에 연결, 그룹, 태그를 공유합니다. 기본적으로 꺼져 있으며 Mac에서는 {tier}이 필요합니다." + "sync": "iCloud Sync는 Apple 기기 간에 연결, 그룹, 태그를 공유합니다. 기본적으로 꺼져 있으며 Mac에서는 {tier}이 필요합니다.", + "linux": "SQL 편집기와 데이터 그리드를 갖춘 Linux 베타 버전." }, "switch": { "title": "연결 가져오기", diff --git a/resources/data/content/ko/linux.json b/resources/data/content/ko/linux.json new file mode 100644 index 00000000..55b6ca24 --- /dev/null +++ b/resources/data/content/ko/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "Linux용 TablePro", + "description": "SQL 편집기와 데이터 그리드를 갖춘 Linux 베타 버전." + }, + "hero": { + "title": "Linux용 TablePro", + "lead": "SQL 편집기와 데이터 그리드를 갖춘 Linux 베타 버전." + }, + "install": { + "title": "베타 설치", + "label": "{system} 명령어", + "lead": "{architectures}용 패키지입니다. 안정 버전과 베타 저장소를 모두 활성화하면 apt 또는 dnf로 업데이트를 받을 수 있습니다.", + "stable": { + "title": "안정 버전", + "body": "안정 버전만 받으려면 안정 버전 저장소를 활성화하세요. 베타 태그는 베타 저장소에만, 안정 버전 태그는 안정 버전 저장소에만 게시됩니다." + }, + "releases": { + "title": "GitHub 패키지", + "body": "GitHub Releases에서 .deb, .rpm, .flatpak 파일을 받으세요. 다음 버전 파일을 설치하여 업데이트하세요." + }, + "guide": { + "label": "Linux 설치 가이드 읽기", + "path": "/linux/install" + } + }, + "databases": { + "title": "데이터베이스", + "lead": "이 드라이버는 Linux 앱에 포함되어 있습니다." + } +} diff --git a/resources/data/content/ko/pricing.json b/resources/data/content/ko/pricing.json index 721bec66..e3a095a1 100644 --- a/resources/data/content/ko/pricing.json +++ b/resources/data/content/ko/pricing.json @@ -50,7 +50,8 @@ "summary": "플랜 종료 시 각 유료 기능의 동작", "intro": "각 유료 기능은 다음과 같이 중지됩니다:" }, - "terms": "라이선스가 허용하는 범위는 이용약관에 명시되어 있습니다." + "terms": "라이선스가 허용하는 범위는 이용약관에 명시되어 있습니다.", + "linux": "Linux는 Mac과 같은 라이선스 모델을 따릅니다. 요금 페이지의 유료 기능은 현재 Mac에서만 사용할 수 있으며 Linux에는 나중에 추가됩니다." }, "billing": { "title": "결제", diff --git a/resources/data/content/pt-BR/download.json b/resources/data/content/pt-BR/download.json index d865bf29..285aa180 100644 --- a/resources/data/content/pt-BR/download.json +++ b/resources/data/content/pt-BR/download.json @@ -59,5 +59,10 @@ "body": "Todas as versões, com suas notas e imagens de disco, estão no GitHub Releases. O histórico de alterações lista o que mudou em cada versão.", "releases": "Todas as versões no GitHub", "changelog": "Histórico de alterações (inglês)" + }, + "linux": { + "title": "TablePro para Linux", + "body": "Uma versão beta para Linux com editor SQL e grade de dados.", + "link": "Ler o guia de instalação no Linux" } } diff --git a/resources/data/content/pt-BR/faq.json b/resources/data/content/pt-BR/faq.json index c8592d75..8aa3d335 100644 --- a/resources/data/content/pt-BR/faq.json +++ b/resources/data/content/pt-BR/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Existe uma versão para Windows ou Linux?", + "question": "Existe uma versão para Linux?", "answer": [ - "Não. Não há versão para Windows. Existe um protótipo para Linux, mas não há nada para instalar nem data de lançamento." + "O aplicativo Linux está em beta. Veja os pacotes e as instruções na página de download." ] }, { diff --git a/resources/data/content/pt-BR/home.json b/resources/data/content/pt-BR/home.json index 785a3d13..e46201fd 100644 --- a/resources/data/content/pt-BR/home.json +++ b/resources/data/content/pt-BR/home.json @@ -9,7 +9,7 @@ "title": "Um cliente de banco de dados nativo." }, "hero": { - "title": "Um cliente de banco de dados nativo.", + "title": "Um cliente de banco de dados nativo para {devices}.", "subtitle": "Execute consultas, explore e edite dados em {featuredEngines} e outros bancos.", "native": "Interfaces nativas, sem Electron nem runtime Java.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro para {devices}", "mac": "O aplicativo de desktop, com versões separadas para {architectures}. Inclui o editor SQL, ferramentas de esquema, assistente AI e servidor MCP.", "ios": "Execute consultas e trabalhe com tabelas suportadas em {devices}. Um aplicativo gratuito separado com túneis SSH e um bloqueio de Face ID opcional.", - "sync": "iCloud Sync compartilha conexões, grupos e tags entre dispositivos Apple. Está desativado por padrão e requer {tier} no Mac." + "sync": "iCloud Sync compartilha conexões, grupos e tags entre dispositivos Apple. Está desativado por padrão e requer {tier} no Mac.", + "linux": "Uma versão beta para Linux com editor SQL e grade de dados." }, "switch": { "title": "Traga suas conexões", diff --git a/resources/data/content/pt-BR/linux.json b/resources/data/content/pt-BR/linux.json new file mode 100644 index 00000000..13d90a9d --- /dev/null +++ b/resources/data/content/pt-BR/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro para Linux", + "description": "Uma versão beta para Linux com editor SQL e grade de dados." + }, + "hero": { + "title": "TablePro para Linux", + "lead": "Uma versão beta para Linux com editor SQL e grade de dados." + }, + "install": { + "title": "Instalar a versão beta", + "label": "Comandos para {system}", + "lead": "Pacotes para {architectures}. Ative os repositórios estável e beta para receber atualizações pelo apt ou dnf.", + "stable": { + "title": "Versões estáveis", + "body": "Para receber apenas versões estáveis, ative o repositório estável. Tags beta publicam apenas nos repositórios beta; tags estáveis, apenas nos estáveis." + }, + "releases": { + "title": "Pacotes no GitHub", + "body": "Baixe arquivos .deb, .rpm e .flatpak em GitHub Releases. Instale o próximo arquivo para atualizar." + }, + "guide": { + "label": "Ler o guia de instalação no Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Bancos de dados", + "lead": "Estes drivers estão incluídos no aplicativo Linux." + } +} diff --git a/resources/data/content/pt-BR/pricing.json b/resources/data/content/pt-BR/pricing.json index 685676f9..ef99981b 100644 --- a/resources/data/content/pt-BR/pricing.json +++ b/resources/data/content/pt-BR/pricing.json @@ -50,7 +50,8 @@ "summary": "O que acontece com cada recurso pago quando um plano termina", "intro": "Cada recurso pago para de funcionar à sua maneira:" }, - "terms": "Os termos de serviço definem o que uma licença permite." + "terms": "Os termos de serviço definem o que uma licença permite.", + "linux": "O Linux segue o mesmo modelo de licenciamento do Mac. Os recursos pagos da página de preços estão disponíveis apenas no Mac por enquanto e chegarão ao Linux depois." }, "billing": { "title": "Cobrança", diff --git a/resources/data/content/vi/download.json b/resources/data/content/vi/download.json index 9211ea85..e4029039 100644 --- a/resources/data/content/vi/download.json +++ b/resources/data/content/vi/download.json @@ -59,5 +59,10 @@ "body": "Mọi bản phát hành, kèm ghi chú và file DMG, đều có trên GitHub Releases. Changelog liệt kê những gì đã thay đổi trong từng phiên bản.", "releases": "Tất cả bản phát hành trên GitHub", "changelog": "Changelog (tiếng Anh)" + }, + "linux": { + "title": "TablePro cho Linux", + "body": "Bản beta cho Linux với SQL editor và data grid.", + "link": "Đọc hướng dẫn cài đặt Linux" } } diff --git a/resources/data/content/vi/faq.json b/resources/data/content/vi/faq.json index 0da5f54b..1b5ebbe3 100644 --- a/resources/data/content/vi/faq.json +++ b/resources/data/content/vi/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "Có phiên bản cho Windows hoặc Linux không?", + "question": "Có phiên bản Linux không?", "answer": [ - "Không. Không có phiên bản cho Windows. Có một bản prototype cho Linux, nhưng không có gì để cài đặt và không có ngày phát hành." + "Ứng dụng Linux đang ở bản beta. Xem gói cài đặt và hướng dẫn trên trang tải về." ] }, { diff --git a/resources/data/content/vi/home.json b/resources/data/content/vi/home.json index dd2610ce..b71e4a4f 100644 --- a/resources/data/content/vi/home.json +++ b/resources/data/content/vi/home.json @@ -9,7 +9,7 @@ "title": "Database client native." }, "hero": { - "title": "Database client native.", + "title": "Database client native cho {devices}.", "subtitle": "Chạy query, xem và chỉnh sửa dữ liệu trên {featuredEngines} và nhiều cơ sở dữ liệu khác.", "native": "Giao diện native, không dùng Electron hay Java runtime.", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "TablePro cho {devices}", "mac": "Ứng dụng desktop có bản build riêng cho {architectures}, gồm SQL editor, công cụ schema, trợ lý AI và MCP server.", "ios": "Chạy query và làm việc với các table được hỗ trợ trên {devices}. Ứng dụng riêng, miễn phí, có SSH tunnel và khóa Face ID tùy chọn.", - "sync": "iCloud Sync chia sẻ connection, nhóm và tag giữa các thiết bị Apple. Tắt theo mặc định và cần gói {tier} trên Mac." + "sync": "iCloud Sync chia sẻ connection, nhóm và tag giữa các thiết bị Apple. Tắt theo mặc định và cần gói {tier} trên Mac.", + "linux": "Bản beta cho Linux với SQL editor và data grid." }, "switch": { "title": "Chuyển connection sang TablePro", diff --git a/resources/data/content/vi/linux.json b/resources/data/content/vi/linux.json new file mode 100644 index 00000000..de8cf503 --- /dev/null +++ b/resources/data/content/vi/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "TablePro cho Linux", + "description": "Bản beta cho Linux với SQL editor và data grid." + }, + "hero": { + "title": "TablePro cho Linux", + "lead": "Bản beta cho Linux với SQL editor và data grid." + }, + "install": { + "title": "Cài bản beta", + "label": "Lệnh cho {system}", + "lead": "Gói cài đặt cho {architectures}. Bật cả kho stable và beta để nhận cập nhật qua apt hoặc dnf.", + "stable": { + "title": "Bản stable", + "body": "Để chỉ nhận bản stable, bật kho stable. Tag beta chỉ phát hành vào kho beta; tag stable chỉ phát hành vào kho stable." + }, + "releases": { + "title": "Gói cài đặt trên GitHub", + "body": "Tải file .deb, .rpm và .flatpak từ GitHub Releases. Cài file phiên bản tiếp theo để cập nhật." + }, + "guide": { + "label": "Đọc hướng dẫn cài đặt Linux", + "path": "/linux/install" + } + }, + "databases": { + "title": "Database", + "lead": "Các driver này có sẵn trong ứng dụng Linux." + } +} diff --git a/resources/data/content/vi/pricing.json b/resources/data/content/vi/pricing.json index 537e7562..c5548331 100644 --- a/resources/data/content/vi/pricing.json +++ b/resources/data/content/vi/pricing.json @@ -50,7 +50,8 @@ "summary": "Từng tính năng trả phí thay đổi thế nào khi gói kết thúc", "intro": "Mỗi tính năng trả phí ngừng hoạt động theo cách riêng:" }, - "terms": "Điều khoản sử dụng nêu rõ một license cho phép những gì." + "terms": "Điều khoản sử dụng nêu rõ một license cho phép những gì.", + "linux": "Linux dùng cùng mô hình license với Mac. Các tính năng trả phí trên trang Giá hiện chỉ có trên Mac và sẽ có trên Linux sau." }, "billing": { "title": "Thanh toán", diff --git a/resources/data/content/zh-Hans/download.json b/resources/data/content/zh-Hans/download.json index be4a1564..89ed188f 100644 --- a/resources/data/content/zh-Hans/download.json +++ b/resources/data/content/zh-Hans/download.json @@ -59,5 +59,10 @@ "body": "每个版本的说明和磁盘映像均在 GitHub Releases 上。更新日志列出了各版本的改动。", "releases": "GitHub 上的所有版本", "changelog": "更新日志(英语)" + }, + "linux": { + "title": "适用于 Linux 的 TablePro", + "body": "带有 SQL 编辑器和数据网格的 Linux 测试版。", + "link": "阅读 Linux 安装指南" } } diff --git a/resources/data/content/zh-Hans/faq.json b/resources/data/content/zh-Hans/faq.json index 976407f3..59a77a9c 100644 --- a/resources/data/content/zh-Hans/faq.json +++ b/resources/data/content/zh-Hans/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "有 Windows 或 Linux 版本吗?", + "question": "有 Linux 版本吗?", "answer": [ - "没有 Windows 版本。Linux 有原型,但没有可安装的版本,也没有发布日期。" + "Linux 应用处于测试阶段。软件包和安装说明请参阅 下载页面。" ] }, { diff --git a/resources/data/content/zh-Hans/home.json b/resources/data/content/zh-Hans/home.json index be9ca2d3..a33a4809 100644 --- a/resources/data/content/zh-Hans/home.json +++ b/resources/data/content/zh-Hans/home.json @@ -9,7 +9,7 @@ "title": "原生数据库客户端。" }, "hero": { - "title": "原生数据库客户端。", + "title": "适用于 {devices} 的原生数据库客户端。", "subtitle": "在 {featuredEngines} 等数据库中运行查询、浏览和编辑数据。", "native": "采用原生界面,不依赖 Electron 或 Java 运行时。", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "{devices} 版 TablePro", "mac": "桌面 App 为 {architectures} 提供独立版本,包含 SQL 编辑器、结构工具、AI 助手和 MCP 服务器。", "ios": "在 {devices} 上运行查询并操作支持的表。这是一款独立的免费 App,支持 SSH 隧道和可选的 Face ID 锁定。", - "sync": "iCloud Sync 在 Apple 设备间共享连接、分组和标签。默认关闭,Mac 上需要 {tier}。" + "sync": "iCloud Sync 在 Apple 设备间共享连接、分组和标签。默认关闭,Mac 上需要 {tier}。", + "linux": "带有 SQL 编辑器和数据网格的 Linux 测试版。" }, "switch": { "title": "迁移连接", diff --git a/resources/data/content/zh-Hans/linux.json b/resources/data/content/zh-Hans/linux.json new file mode 100644 index 00000000..179a94b5 --- /dev/null +++ b/resources/data/content/zh-Hans/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "适用于 Linux 的 TablePro", + "description": "带有 SQL 编辑器和数据网格的 Linux 测试版。" + }, + "hero": { + "title": "适用于 Linux 的 TablePro", + "lead": "带有 SQL 编辑器和数据网格的 Linux 测试版。" + }, + "install": { + "title": "安装测试版", + "label": "{system} 命令", + "lead": "适用于 {architectures} 的软件包。请同时启用稳定版和测试版软件仓库,通过 apt 或 dnf 获取更新。", + "stable": { + "title": "稳定版", + "body": "如只需稳定版,请启用稳定版仓库。测试版标签仅发布到测试版仓库;稳定版标签仅发布到稳定版仓库。" + }, + "releases": { + "title": "GitHub 软件包", + "body": "从 GitHub Releases 获取 .deb、.rpm 和 .flatpak 文件。安装下一个版本的文件即可更新。" + }, + "guide": { + "label": "阅读 Linux 安装指南", + "path": "/linux/install" + } + }, + "databases": { + "title": "数据库", + "lead": "Linux 应用包含这些驱动程序。" + } +} diff --git a/resources/data/content/zh-Hans/pricing.json b/resources/data/content/zh-Hans/pricing.json index 6dd60f25..e800f4ff 100644 --- a/resources/data/content/zh-Hans/pricing.json +++ b/resources/data/content/zh-Hans/pricing.json @@ -50,7 +50,8 @@ "summary": "方案结束时各付费功能的行为", "intro": "各付费功能会按以下方式停止:" }, - "terms": "服务条款说明了许可证允许的使用范围。" + "terms": "服务条款说明了许可证允许的使用范围。", + "linux": "Linux 采用与 Mac 相同的许可模式。定价页面列出的付费功能目前仅限 Mac,以后将加入 Linux。" }, "billing": { "title": "账单", diff --git a/resources/data/content/zh-Hant/download.json b/resources/data/content/zh-Hant/download.json index b11eb705..4b8c0695 100644 --- a/resources/data/content/zh-Hant/download.json +++ b/resources/data/content/zh-Hant/download.json @@ -59,5 +59,10 @@ "body": "每個版本的說明與磁碟映像檔均在 GitHub Releases 上。更新紀錄列出了各版本的變更。", "releases": "GitHub 上的所有版本", "changelog": "更新紀錄(英文)" + }, + "linux": { + "title": "適用於 Linux 的 TablePro", + "body": "附有 SQL 編輯器和資料網格的 Linux 測試版。", + "link": "閱讀 Linux 安裝指南" } } diff --git a/resources/data/content/zh-Hant/faq.json b/resources/data/content/zh-Hant/faq.json index 9842808d..e7ba417e 100644 --- a/resources/data/content/zh-Hant/faq.json +++ b/resources/data/content/zh-Hant/faq.json @@ -87,9 +87,9 @@ }, { "id": "windows-linux", - "question": "有 Windows 或 Linux 版本嗎?", + "question": "有 Linux 版本嗎?", "answer": [ - "沒有 Windows 版本。Linux 有原型,但沒有可安裝的版本,也沒有發佈日期。" + "Linux 應用程式目前為測試版。套件和安裝說明請參閱 下載頁面。" ] }, { diff --git a/resources/data/content/zh-Hant/home.json b/resources/data/content/zh-Hant/home.json index 60bb9dda..5d9faadc 100644 --- a/resources/data/content/zh-Hant/home.json +++ b/resources/data/content/zh-Hant/home.json @@ -9,7 +9,7 @@ "title": "原生資料庫用戶端。" }, "hero": { - "title": "原生資料庫用戶端。", + "title": "適用於 {devices} 的原生資料庫用戶端。", "subtitle": "在 {featuredEngines} 等資料庫中執行查詢、瀏覽及編輯資料。", "native": "採用原生介面,不依賴 Electron 或 Java 執行階段。", "macCaption": "{requirement} · {architectures}", @@ -97,7 +97,8 @@ "cardTitle": "{devices} 版 TablePro", "mac": "桌面 App 為 {architectures} 提供獨立版本,包含 SQL 編輯器、結構工具、AI 助手和 MCP 伺服器。", "ios": "在 {devices} 上執行查詢並操作支援的資料表。這是一款獨立的免費 App,支援 SSH 通道和選用的 Face ID 鎖定。", - "sync": "iCloud Sync 在 Apple 裝置間共享連線、群組和標籤。預設關閉,Mac 上需要 {tier}。" + "sync": "iCloud Sync 在 Apple 裝置間共享連線、群組和標籤。預設關閉,Mac 上需要 {tier}。", + "linux": "附有 SQL 編輯器和資料網格的 Linux 測試版。" }, "switch": { "title": "移轉連線", diff --git a/resources/data/content/zh-Hant/linux.json b/resources/data/content/zh-Hant/linux.json new file mode 100644 index 00000000..f01e2445 --- /dev/null +++ b/resources/data/content/zh-Hant/linux.json @@ -0,0 +1,31 @@ +{ + "seo": { + "title": "適用於 Linux 的 TablePro", + "description": "附有 SQL 編輯器和資料網格的 Linux 測試版。" + }, + "hero": { + "title": "適用於 Linux 的 TablePro", + "lead": "附有 SQL 編輯器和資料網格的 Linux 測試版。" + }, + "install": { + "title": "安裝測試版", + "label": "{system} 指令", + "lead": "適用於 {architectures} 的套件。請同時啟用穩定版和測試版套件庫,透過 apt 或 dnf 取得更新。", + "stable": { + "title": "穩定版", + "body": "如只需穩定版,請啟用穩定版套件庫。測試版標籤僅發佈到測試版套件庫;穩定版標籤僅發佈到穩定版套件庫。" + }, + "releases": { + "title": "GitHub 套件", + "body": "從 GitHub Releases 取得 .deb、.rpm 和 .flatpak 檔案。安裝下一個版本的檔案即可更新。" + }, + "guide": { + "label": "閱讀 Linux 安裝指南", + "path": "/linux/install" + } + }, + "databases": { + "title": "資料庫", + "lead": "Linux 應用程式包含這些驅動程式。" + } +} diff --git a/resources/data/content/zh-Hant/pricing.json b/resources/data/content/zh-Hant/pricing.json index f6821865..c21b7caf 100644 --- a/resources/data/content/zh-Hant/pricing.json +++ b/resources/data/content/zh-Hant/pricing.json @@ -50,7 +50,8 @@ "summary": "方案結束時各付費功能的行為", "intro": "各付費功能會按以下方式停止:" }, - "terms": "服務條款說明了授權允許的使用範圍。" + "terms": "服務條款說明了授權允許的使用範圍。", + "linux": "Linux 採用與 Mac 相同的授權模式。定價頁面列出的付費功能目前僅限 Mac,日後將加入 Linux。" }, "billing": { "title": "帳務", diff --git a/resources/data/platforms.json b/resources/data/platforms.json index 1c614fe2..1a6f9b40 100644 --- a/resources/data/platforms.json +++ b/resources/data/platforms.json @@ -66,7 +66,37 @@ "price": { "amount": 0, "inAppPurchases": false }, "appLanguages": ["en", "vi", "ko", "zh-Hans", "zh-Hant"] }, - { "id": "linux", "status": "prototype" }, + { + "id": "linux", + "status": "beta", + "deviceNames": ["Linux"], + "page": "/linux", + "architectures": ["amd64", "arm64"], + "destinations": [ + { + "kind": "apt", + "system": "Ubuntu", + "versions": ["26.04", "26.10"], + "orLater": false, + "beta": ["sudo add-apt-repository ppa:tablepro/tablepro", "sudo add-apt-repository ppa:tablepro/tablepro-beta", "sudo apt install tablepro"], + "stable": ["sudo add-apt-repository ppa:tablepro/tablepro", "sudo apt install tablepro"] + }, + { + "kind": "dnf", + "system": "Fedora", + "versions": ["44"], + "orLater": true, + "beta": ["sudo dnf copr enable @tablepro/tablepro", "sudo dnf copr enable @tablepro/tablepro-beta", "sudo dnf install tablepro"], + "stable": ["sudo dnf copr enable @tablepro/tablepro", "sudo dnf install tablepro"] + }, + { + "kind": "releases", + "url": "https://github.com/TableProApp/TablePro/releases" + } + ], + "linuxEngines": ["postgresql", "mysql", "mariadb", "sqlserver", "clickhouse", "cassandra", "scylladb", "sqlite", "duckdb", "redis", "mongodb"], + "appLanguages": ["en", "vi"] + }, { "id": "windows", "status": "none" } ] } diff --git a/resources/js/components/download/command-block.tsx b/resources/js/components/download/command-block.tsx index 41e560d3..55a3d11f 100644 --- a/resources/js/components/download/command-block.tsx +++ b/resources/js/components/download/command-block.tsx @@ -2,8 +2,8 @@ import CopyButton from '@/components/ui/copy-button'; import { useI18n } from '@/i18n'; interface CommandBlockProps { - /** The command exactly as it is copied, without a prompt. */ - command: string; + /** The command exactly as it is copied, without a prompt; several run one per line. */ + command: string | readonly string[]; /** The title bar's text, such as "Terminal". */ title: string; /** Names the command for the copy button and the scroll region: "Homebrew command". */ @@ -20,20 +20,23 @@ interface CommandBlockProps { */ export default function CommandBlock({ command, title, label }: CommandBlockProps) { const { m } = useI18n(); + const lines = typeof command === 'string' ? [command] : command; return (
{title} - +
-
-                    
-                    {command}
-                
+ {lines.map((line) => ( +
+                        
+                        {line}
+                    
+ ))}
); diff --git a/resources/js/components/home/hero.tsx b/resources/js/components/home/hero.tsx index e651c2de..921645fe 100644 --- a/resources/js/components/home/hero.tsx +++ b/resources/js/components/home/hero.tsx @@ -2,7 +2,9 @@ import AssetSlot, { useShownSlot } from '@/components/ui/asset-slot'; import Container from '@/components/ui/container'; import LocaleLink from '@/components/ui/locale-link'; import { textLinkClasses } from '@/components/ui/text-link'; -import { Trans } from '@/i18n'; +import { Trans, useI18n } from '@/i18n'; +import { joinList } from '@/i18n/format'; +import { availablePlatforms } from '@/lib/data/platforms'; import type { Availability } from './availability'; import PlatformActions from './platform-actions'; import type { HomeContent } from './types'; @@ -17,13 +19,6 @@ interface HeroProps { /** * Section 1, `#top` (sitemap §D; positioning §3; design-system §8.1). * - * The H1 and subtitle are identity copy: no platform, version or number, so - * they hold when a platform ships. Platforms appear only in the captions under - * the two actions, which are built from platforms.json. "and more" jumps to the - * databases section; "See pricing" to `#pricing`, where shipped Mac builds - * already send people with `/?ref=…#pricing`. What "native" means sits under - * the actions, beside the pricing line, not in the identity copy. - * * The two actions are a row of cells across the page grid, the hero's one * piece of the frame (design-system §4.7); the headline above them stays * unlined. @@ -35,13 +30,20 @@ interface HeroProps { */ export default function Hero({ content, availability, featuredEngines }: HeroProps) { const shown = useShownSlot(); + const { fmt, m } = useI18n(); + const devices = joinList( + availablePlatforms().flatMap((platform) => + platform.deviceNames.map((name) => platform.status === 'beta' ? `${name} (${m.platforms.status.beta})` : name), + ), + m.common.list, + ); return (

- {content.title} + {fmt(content.title, { devices })}

)} + + {linux !== null && ( +
+

+ {fmt(content.cardTitle, { devices: linuxDevices })} + {linux.status === 'beta' && {m.platforms.status.beta}} +

+

{content.linux}

+

+ + {fmt(content.cardTitle, { devices: linuxDevices })} + + +

+
+ )}
); diff --git a/resources/js/components/site/site-links.ts b/resources/js/components/site/site-links.ts index 6ad7c31d..eeb8482d 100644 --- a/resources/js/components/site/site-links.ts +++ b/resources/js/components/site/site-links.ts @@ -57,14 +57,17 @@ export interface PlatformPage { } /** - * One link per released platform that has a page of its own: today `/ios`, - * labelled "iPhone & iPad". The Mac's page is /download, which the header - * already links. A platform that ships with a page gets its link from data. + * One link per released or beta platform that has a page of its own: `/ios`, + * labelled "iPhone & iPad", and `/linux`. The Mac's page is /download, which + * the header already links. A platform that ships with a page gets its link + * from data. */ export const PLATFORM_PAGES: PlatformPage[] = platformData.platforms.flatMap((candidate) => { - const platform = releasedPlatform(candidate.id); + const available = candidate.status === 'released' || candidate.status === 'beta'; - return platform?.page ? [{ id: platform.id, href: platform.page, deviceNames: platform.deviceNames }] : []; + return available && typeof candidate.page === 'string' && candidate.deviceNames + ? [{ id: candidate.id, href: candidate.page, deviceNames: candidate.deviceNames }] + : []; }); /** External destinations, from facts.json. */ diff --git a/resources/js/i18n/messages/de/platforms.ts b/resources/js/i18n/messages/de/platforms.ts index a5141fe8..b8f2e8a5 100644 --- a/resources/js/i18n/messages/de/platforms.ts +++ b/resources/js/i18n/messages/de/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Kostenlos, ohne In-App-Käufe", "status": { "released": "Verfügbar", + "beta": "Beta", "prototype": "Nur ein Prototyp. Nichts zum Installieren und kein Erscheinungstermin.", "none": "Nicht verfügbar, kein Erscheinungstermin." }, diff --git a/resources/js/i18n/messages/en/platforms.ts b/resources/js/i18n/messages/en/platforms.ts index 21fb75b0..c64f47f6 100644 --- a/resources/js/i18n/messages/en/platforms.ts +++ b/resources/js/i18n/messages/en/platforms.ts @@ -30,6 +30,7 @@ export default { free: 'Free, with no in-app purchases', status: { released: 'Available', + beta: 'Beta', prototype: 'A prototype only. Nothing to install, and no release date.', none: 'Not available, and no release date.', }, diff --git a/resources/js/i18n/messages/es/platforms.ts b/resources/js/i18n/messages/es/platforms.ts index f2cd63c7..1016d77d 100644 --- a/resources/js/i18n/messages/es/platforms.ts +++ b/resources/js/i18n/messages/es/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Gratis, sin compras dentro de la app", "status": { "released": "Disponible", + "beta": "Beta", "prototype": "Solo un prototipo. No hay nada que instalar ni fecha de lanzamiento.", "none": "No disponible, sin fecha de lanzamiento." }, diff --git a/resources/js/i18n/messages/fr/platforms.ts b/resources/js/i18n/messages/fr/platforms.ts index b04f1e4b..fa743ba0 100644 --- a/resources/js/i18n/messages/fr/platforms.ts +++ b/resources/js/i18n/messages/fr/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Gratuit, sans achats intégrés", "status": { "released": "Disponible", + "beta": "Bêta", "prototype": "Un prototype uniquement. Rien à installer, aucune date de sortie.", "none": "Non disponible, aucune date de sortie." }, diff --git a/resources/js/i18n/messages/id/platforms.ts b/resources/js/i18n/messages/id/platforms.ts index a54e0b28..d3ada165 100644 --- a/resources/js/i18n/messages/id/platforms.ts +++ b/resources/js/i18n/messages/id/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Gratis, tanpa pembelian dalam aplikasi", "status": { "released": "Tersedia", + "beta": "Beta", "prototype": "Hanya prototipe. Tidak ada yang dapat diinstal dan tidak ada tanggal rilis.", "none": "Tidak tersedia dan tidak ada tanggal rilis." }, diff --git a/resources/js/i18n/messages/it/platforms.ts b/resources/js/i18n/messages/it/platforms.ts index 7c01468b..c0ffe9af 100644 --- a/resources/js/i18n/messages/it/platforms.ts +++ b/resources/js/i18n/messages/it/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Gratuita, senza acquisti in-app", "status": { "released": "Disponibile", + "beta": "Beta", "prototype": "Solo un prototipo. Nulla da installare e nessuna data di rilascio.", "none": "Non disponibile e nessuna data di rilascio." }, diff --git a/resources/js/i18n/messages/ja/platforms.ts b/resources/js/i18n/messages/ja/platforms.ts index 0c4738e3..b59d539c 100644 --- a/resources/js/i18n/messages/ja/platforms.ts +++ b/resources/js/i18n/messages/ja/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "無料、アプリ内課金なし", "status": { "released": "利用可能", + "beta": "ベータ版", "prototype": "プロトタイプのみです。インストールできるものはなく、リリース日の予定もありません。", "none": "提供していません。リリース日の予定もありません。" }, diff --git a/resources/js/i18n/messages/ko/platforms.ts b/resources/js/i18n/messages/ko/platforms.ts index 2662a2f3..e1569fb4 100644 --- a/resources/js/i18n/messages/ko/platforms.ts +++ b/resources/js/i18n/messages/ko/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "무료, 앱 내 구입 없음", "status": { "released": "사용 가능", + "beta": "베타", "prototype": "프로토타입만 있습니다. 설치할 수 있는 앱과 출시 일정은 없습니다.", "none": "제공되지 않으며 출시 일정도 없습니다." }, diff --git a/resources/js/i18n/messages/pt-BR/platforms.ts b/resources/js/i18n/messages/pt-BR/platforms.ts index 22c13d16..c1d059d2 100644 --- a/resources/js/i18n/messages/pt-BR/platforms.ts +++ b/resources/js/i18n/messages/pt-BR/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "Grátis, sem compras no app", "status": { "released": "Disponível", + "beta": "Beta", "prototype": "Apenas um protótipo. Nada para instalar, sem data de lançamento.", "none": "Indisponível, sem data de lançamento." }, diff --git a/resources/js/i18n/messages/vi/platforms.ts b/resources/js/i18n/messages/vi/platforms.ts index 27244dd3..58cb26e3 100644 --- a/resources/js/i18n/messages/vi/platforms.ts +++ b/resources/js/i18n/messages/vi/platforms.ts @@ -22,6 +22,7 @@ export default { free: 'Miễn phí, không có mua hàng trong ứng dụng', status: { released: 'Đã phát hành', + beta: 'Beta', prototype: 'Chỉ có bản prototype. Không có gì để cài đặt và không có ngày phát hành.', none: 'Không có bản cài đặt, và không có ngày phát hành.', }, diff --git a/resources/js/i18n/messages/zh-Hans/platforms.ts b/resources/js/i18n/messages/zh-Hans/platforms.ts index 572a630d..645c0654 100644 --- a/resources/js/i18n/messages/zh-Hans/platforms.ts +++ b/resources/js/i18n/messages/zh-Hans/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "免费,无应用内购买", "status": { "released": "已推出", + "beta": "测试版", "prototype": "仅有原型。没有可安装的版本,也没有发布日期。", "none": "不提供,也没有发布日期。" }, diff --git a/resources/js/i18n/messages/zh-Hant/platforms.ts b/resources/js/i18n/messages/zh-Hant/platforms.ts index bb1202d0..8d1b6d81 100644 --- a/resources/js/i18n/messages/zh-Hant/platforms.ts +++ b/resources/js/i18n/messages/zh-Hant/platforms.ts @@ -22,6 +22,7 @@ export default { "free": "免費,無 App 內購買", "status": { "released": "已推出", + "beta": "測試版", "prototype": "僅有原型。沒有可安裝的版本,也沒有發佈日期。", "none": "不提供,也沒有發佈日期。" }, diff --git a/resources/js/lib/data/platforms.ts b/resources/js/lib/data/platforms.ts index 91626bfc..5a5fd20f 100644 --- a/resources/js/lib/data/platforms.ts +++ b/resources/js/lib/data/platforms.ts @@ -3,8 +3,9 @@ * needs, and where to get it. * * Only a `released` platform carries requirements, destinations and a - * release. Linux and Windows are listed with their status and nothing else, - * so no component can render a requirement, a button or a date for them. + * release. A `beta` platform (Linux) carries its page, packages and engines + * but no release or date. Any other platform is listed with its status and + * nothing else, so no component can render a button for it. * Every phrase around these values (the "or later" sentence, "Apple silicon", * "Mac app") is a `platforms` catalog entry; this module joins them. * @@ -18,7 +19,7 @@ import { joinList, type ListStyle } from '../../i18n/format.ts'; export type PlatformId = 'mac' | 'ios' | 'linux' | 'windows'; -export type PlatformStatus = 'released' | 'prototype' | 'none'; +export type PlatformStatus = 'released' | 'beta' | 'prototype' | 'none'; export type MacArchitecture = 'arm64' | 'x86_64'; @@ -83,6 +84,29 @@ export interface IosPlatform extends ReleasedPlatformBase { price: { amount: number; inAppPurchases: boolean }; } +export interface LinuxRepository { + kind: 'apt' | 'dnf'; + /** The distribution's name, never translated: `Ubuntu`. */ + system: string; + versions: string[]; + /** `Fedora 44 or later` rather than `Ubuntu 26.04 and 26.10`. */ + orLater: boolean; + beta: string[]; + stable: string[]; +} + +export interface LinuxPlatform { + id: 'linux'; + status: 'beta'; + deviceNames: string[]; + page: string; + architectures: string[]; + destinations: (LinuxRepository | { kind: 'releases'; url: string })[]; + /** Engine ids the Linux app connects to, in its order. Name them; never count them. */ + linuxEngines: string[]; + appLanguages: string[]; +} + export interface UnreleasedPlatform { id: 'linux' | 'windows'; status: 'prototype' | 'none'; @@ -90,7 +114,10 @@ export interface UnreleasedPlatform { export type ReleasedPlatform = MacPlatform | IosPlatform; -export type Platform = ReleasedPlatform | UnreleasedPlatform; +/** A platform with something to install, a beta included. */ +export type AvailablePlatform = ReleasedPlatform | LinuxPlatform; + +export type Platform = AvailablePlatform | UnreleasedPlatform; export interface PlatformsData { verifiedAt: string; @@ -115,11 +142,40 @@ export function isReleased(platform: Platform): platform is ReleasedPlatform { return platform.status === 'released'; } +export function isAvailable(platform: Platform): platform is AvailablePlatform { + return platform.status === 'released' || platform.status === 'beta'; +} + /** Every platform with something to install, in data order. */ +export function availablePlatforms(): AvailablePlatform[] { + return PLATFORMS.platforms.filter(isAvailable); +} + +/** Released platforms with version metadata. */ export function releasedPlatforms(): ReleasedPlatform[] { return PLATFORMS.platforms.filter(isReleased); } +/** The Linux app while it has something to install, else null. */ +export function linuxPlatform(): LinuxPlatform | null { + const linux = PLATFORMS.platforms.find((platform) => platform.id === 'linux'); + + return linux !== undefined && isAvailable(linux) ? (linux as LinuxPlatform) : null; +} + +export function linuxRepositories(linux: LinuxPlatform): LinuxRepository[] { + return linux.destinations.filter((entry): entry is LinuxRepository => entry.kind === 'apt' || entry.kind === 'dnf'); +} + +/** `Ubuntu 26.04 and 26.10`, `Fedora 44 or later`. */ +export function distributionText(repository: LinuxRepository, strings: PlatformStrings, style: ListStyle): string { + if (repository.orLater) { + return interpolate(strings.requirement.unnamed, { systems: repository.system, version: repository.versions[0] ?? '' }); + } + + return `${repository.system} ${joinList(repository.versions, style)}`; +} + export function macPlatform(): MacPlatform { return find('mac') as MacPlatform; } @@ -172,7 +228,7 @@ export function architecturesText(strings: PlatformStrings): string { ); } -/** `Mac, iPhone and iPad`: every released platform's devices, joined with the locale's list style. */ +/** The released Apple apps used by the existing engine and feature pages. */ export function deviceList(style: ListStyle): string { return joinList( releasedPlatforms().flatMap((platform) => platform.deviceNames), @@ -181,7 +237,7 @@ export function deviceList(style: ListStyle): string { } /** One platform's devices: `iPhone and iPad`, or `iPhone & iPad` with the short list style. */ -export function devicesOf(platform: ReleasedPlatform, style: ListStyle): string { +export function devicesOf(platform: AvailablePlatform, style: ListStyle): string { return joinList(platform.deviceNames, style); } diff --git a/resources/js/pages/Download.tsx b/resources/js/pages/Download.tsx index 44cf0c64..f0f5d4f1 100644 --- a/resources/js/pages/Download.tsx +++ b/resources/js/pages/Download.tsx @@ -10,12 +10,13 @@ import PageHeader from '@/components/ui/page-header'; import Section from '@/components/ui/section'; import TextLink, { textLinkClasses } from '@/components/ui/text-link'; import { requirementLine } from '@/components/download/format'; +import Badge from '@/components/ui/badge'; import IosCard from '@/components/download/ios-card'; import MacCard, { UI_TAGS } from '@/components/download/mac-card'; import type { DownloadPageProps } from '@/components/download/types'; import { LOCALES, Trans, useI18n, type Messages } from '@/i18n'; import { joinList, keepTogether } from '@/i18n/format'; -import { architecturesText } from '@/lib/data/platforms'; +import { architecturesText, linuxPlatform } from '@/lib/data/platforms'; import { PRICING } from '@/lib/data/pricing'; import { appStoreFirst, classifyDevice, type DeviceKind } from '@/lib/device'; import { absoluteUrl, graph, iosAppNode, macAppId, macAppNode, webPageNode, type JsonLdGraph } from '@/lib/structured-data'; @@ -180,6 +181,16 @@ export default function Download({ content, release, mac, ios, unreleased, links + {linuxPlatform() !== null && ( +
+ {m.platforms.status.beta} +

{content.linux.body}

+ + {content.linux.link} + +
+ )} + {/* What to do after the download: one section each, so the page frame's joins separate them (design-system §4.7). */}
diff --git a/resources/js/pages/Linux.tsx b/resources/js/pages/Linux.tsx new file mode 100644 index 00000000..fecdb281 --- /dev/null +++ b/resources/js/pages/Linux.tsx @@ -0,0 +1,138 @@ +import { usePage } from '@inertiajs/react'; +import CommandBlock from '@/components/download/command-block'; +import type { SiteLinks } from '@/components/faq/content-links'; +import SEOHead from '@/components/seo/seo-head'; +import Badge from '@/components/ui/badge'; +import LocaleLink from '@/components/ui/locale-link'; +import PageHeader from '@/components/ui/page-header'; +import Section from '@/components/ui/section'; +import TextLink, { textLinkClasses } from '@/components/ui/text-link'; +import { LOCALES, Trans, useI18n } from '@/i18n'; +import { joinList } from '@/i18n/format'; +import { PUBLISHER } from '@/lib/data/facts'; +import { distributionText, linuxPlatform, linuxRepositories } from '@/lib/data/platforms'; +import { absoluteUrl, graph, organizationNode, webPageNode } from '@/lib/structured-data'; +import LandingLayout from '@/layouts/landing-layout'; + +type LinuxContent = typeof import('@data/content/en/linux.json'); + +interface LinuxProps { + content: LinuxContent; + /** The engines the Linux app connects to, empty while it has nothing to install. */ + engines: { id: string; name: string; href: string | null }[]; + links: SiteLinks; + organizationProfiles: string[]; +} + +export default function Linux({ content, engines, links, organizationProfiles }: LinuxProps) { + const { canonicalBaseUrl } = usePage().props; + const { locale, m, fmt, path } = useI18n(); + const linux = linuxPlatform(); + const repositories = linux !== null ? linuxRepositories(linux) : []; + const releases = linux?.destinations.find((entry) => entry.kind === 'releases') ?? null; + const context = { baseUrl: canonicalBaseUrl, inLanguage: LOCALES.supported[locale].hreflang }; + + const jsonLd = graph([ + organizationNode(canonicalBaseUrl, { description: m.seo.product.short, sameAs: organizationProfiles, publisher: PUBLISHER }), + webPageNode(context, { + url: absoluteUrl(canonicalBaseUrl, path('/linux')), + name: content.seo.title, + description: content.seo.description, + }), + ]); + + return ( + + + + +
+ {linux !== null && {m.platforms.status.beta}} +
+
+ + {linux !== null && ( +
+
+

+ {fmt(content.install.lead, { architectures: joinList(linux.architectures, m.common.list) })} +

+ + {repositories.map((repository) => ( +
+

{distributionText(repository, m.platforms, m.common.list)}

+
+ +
+
+ ))} + +
+

{content.install.stable.title}

+

{content.install.stable.body}

+
+ {repositories.map((repository) => ( + + ))} +
+
+ + {releases !== null && 'url' in releases && ( +
+

{content.install.releases.title}

+

+ ( + + {text} + + ), + }} + /> +

+
+ )} + + {links.docs !== null && ( +

+ + {content.install.guide.label} + +

+ )} + +
+
+ )} + + {engines.length > 0 && ( +
+
    + {engines.map((engine) => ( +
  • + {engine.href !== null ? ( + + {engine.name} + + ) : ( + engine.name + )} +
  • + ))} +
+
+ )} +
+ ); +} diff --git a/resources/js/pages/Pricing.tsx b/resources/js/pages/Pricing.tsx index a3c2e618..64813073 100644 --- a/resources/js/pages/Pricing.tsx +++ b/resources/js/pages/Pricing.tsx @@ -169,6 +169,7 @@ export default function Pricing({ content, paidFeatures, featuredEngines, compar * lists run from rail to rail (design-system §4.7). */}
+

{content.license.linux}

{Object.entries(content.license.items).map(([key, item]) => ( diff --git a/routes/localized.php b/routes/localized.php index 30a5609e..68b706ed 100644 --- a/routes/localized.php +++ b/routes/localized.php @@ -12,6 +12,7 @@ use App\Http\Controllers\IntegrationController; use App\Http\Controllers\IosController; use App\Http\Controllers\LegalController; +use App\Http\Controllers\LinuxController; use App\Http\Controllers\PricingController; use App\Http\Controllers\SecurityController; use App\Http\Controllers\SponsorsController; @@ -38,7 +39,7 @@ | app/Support/Content/Slugs, never from a content directory read here. | `route:cache` rebuilds only when PHP changes, so a slug that existed only | as a file would ship without a route. -| 2. No root-level path may equal a locale prefix (`vi`), and `ios`, `features`, +| 2. No root-level path may equal a locale prefix (`vi`), and `ios`, `linux`, `features`, | `databases`, `compare`, `integrations`, `pricing` and `brand` must never | join the database slugs. LocaleRoutingTest and LocalesDataTest guard both. | 3. The blog and integration slugs stay patterns: whether a post or an @@ -57,6 +58,7 @@ Route::get('/', HomeController::class)->name('landing.home'); Route::get('/download', DownloadController::class)->name('landing.download'); Route::get('/ios', IosController::class)->name('landing.ios'); +Route::get('/linux', LinuxController::class)->name('landing.linux'); Route::get('/pricing', PricingController::class)->name('landing.pricing'); Route::get('/faq', FaqController::class)->name('landing.faq'); Route::get('/about', AboutController::class)->name('landing.about'); diff --git a/tests/Feature/Content/PositioningGuardsTest.php b/tests/Feature/Content/PositioningGuardsTest.php index 05e1dbce..deb0b6ce 100644 --- a/tests/Feature/Content/PositioningGuardsTest.php +++ b/tests/Feature/Content/PositioningGuardsTest.php @@ -299,7 +299,7 @@ function positioningUnreleasedNames(string $locale): array $unreleased = []; foreach (contentGuardDecode(resource_path('data/platforms.json'))['platforms'] as $platform) { - if (($platform['status'] ?? null) !== 'released') { + if (! in_array($platform['status'] ?? null, ['released', 'beta'], true)) { $unreleased[] = $names["names.{$platform['id']}"] ?? ucfirst((string) $platform['id']); } } diff --git a/tests/Feature/Data/PlatformsDataTest.php b/tests/Feature/Data/PlatformsDataTest.php index e94e6751..a9415b3d 100644 --- a/tests/Feature/Data/PlatformsDataTest.php +++ b/tests/Feature/Data/PlatformsDataTest.php @@ -35,12 +35,12 @@ function platformsDataEntry(string $id): array expect(array_column($data['platforms'], 'id'))->toBe(['mac', 'ios', 'linux', 'windows']); foreach ($data['platforms'] as $platform) { - expect($platform['status'])->toBeIn(['released', 'prototype', 'none']); + expect($platform['status'])->toBeIn(['released', 'beta', 'prototype', 'none']); } expect(platformsDataEntry('mac')['status'])->toBe('released'); expect(platformsDataEntry('ios')['status'])->toBe('released'); - expect(platformsDataEntry('linux')['status'])->toBe('prototype'); + expect(platformsDataEntry('linux')['status'])->toBe('beta'); expect(platformsDataEntry('windows')['status'])->toBe('none'); }); @@ -48,6 +48,13 @@ function platformsDataEntry(string $id): array $common = ['id', 'status', 'deviceNames', 'page', 'requirements', 'destinations', 'release', 'appLanguages']; foreach (platformsDataFile()['platforms'] as $platform) { + if ($platform['status'] === 'beta') { + expect($platform)->toHaveKeys(['deviceNames', 'page', 'architectures', 'destinations', 'linuxEngines', 'appLanguages']); + expect($platform)->not->toHaveKeys(['release', 'requirements']); + + continue; + } + if ($platform['status'] !== 'released') { expect(array_keys($platform))->toBe(['id', 'status'], "{$platform['id']} is not released, so it carries no requirement, destination or date"); diff --git a/tests/Feature/Landing/FaqPageTest.php b/tests/Feature/Landing/FaqPageTest.php index 06f82246..b197db4d 100644 --- a/tests/Feature/Landing/FaqPageTest.php +++ b/tests/Feature/Landing/FaqPageTest.php @@ -168,11 +168,11 @@ function faqKnownTags(): array ->not->toContain('daily usage report'); }); -it('answers the Windows and Linux question without a promise', function (): void { +it('answers the Linux question with beta availability', function (): void { $answer = collect(faqContent('en')['groups'])->firstWhere('id', 'platforms')['items']; $answer = collect($answer)->firstWhere('id', 'windows-linux')['answer'][0]; - expect($answer)->toBe('No. There is no Windows version. A Linux prototype exists, but there is nothing to install and no release date.'); + expect($answer)->toBe('The Linux app is in beta. See the download page for packages and installation instructions.'); }); it('server-renders every group, with no FAQPage markup', function (string $path): void { diff --git a/tests/Feature/Landing/HomepageRenderTest.php b/tests/Feature/Landing/HomepageRenderTest.php index b8b58643..fa531ecb 100644 --- a/tests/Feature/Landing/HomepageRenderTest.php +++ b/tests/Feature/Landing/HomepageRenderTest.php @@ -74,7 +74,7 @@ function homeSectionIds(string $html): array ->assertInertia(fn(AssertableInertia $page) => $page ->component('Home') ->where('locale', 'en') - ->where('content.hero.title', 'A native database client.') + ->where('content.hero.title', 'A native database client for {devices}.') ->where('content.seo.title', 'TablePro: native database client for {deviceList}') ->where('apiOrigin', 'https://api.tablepro.app') ->missing('checkout') @@ -97,7 +97,7 @@ function homeSectionIds(string $html): array ->assertInertia(fn(AssertableInertia $page) => $page ->component('Home') ->where('locale', 'vi') - ->where('content.hero.title', 'Database client native.') + ->where('content.hero.title', 'Database client native cho {devices}.') ->where('content.seo.title', 'TablePro: database client native cho {deviceList}') ->missing('downloadUrls') ->missing('latestRelease') @@ -479,18 +479,18 @@ function homeSectionIds(string $html): array ->not->toContain('"datePublished"'); })->with(['/', '/vi'])->group('ssr'); - it('names the platforms only in the availability lines, from data', function (): void { + it('names available platforms in the headline and availability lines, from data', function (): void { // The requirement phrase is held together with no-break spaces ("Apple silicon or Intel"); compare as text. $text = static fn(string $path): string => str_replace("\u{00A0}", ' ', ssrHome($path)); expect($text('/')) - ->toContain('A native database client.') + ->toContain('A native database client for Mac, iPhone, iPad and Linux (Beta).') ->toContain('macOS 13 Ventura or later · Apple silicon or Intel') ->toContain('iPhone and iPad · iOS and iPadOS 18 or later') ->toContain('Download for Mac'); expect($text('/vi')) - ->toContain('Database client native.') + ->toContain('Database client native cho Mac, iPhone, iPad và Linux (Beta).') ->toContain('macOS 13 Ventura trở lên · Apple silicon hoặc Intel') ->toContain('iPhone và iPad · iOS và iPadOS 18 trở lên') ->toContain('Tải về cho Mac'); @@ -694,7 +694,8 @@ function homeSectionIds(string $html): array $hero = html_entity_decode(strip_tags(substr($html, (int) $start, (int) strpos($html, 'id="databases"') - (int) $start)), ENT_QUOTES | ENT_HTML5); preg_match('#(.*?)#', $copy['business'], $pricingLink); - $headline = strpos($hero, $copy['title']); + $headlineText = HTMLDocument::createFromString($html, LIBXML_NOERROR)->getElementById('top-title')->textContent; + $headline = strpos($hero, $headlineText); $pricing = strpos($hero, $pricingLink[1]); $native = strpos($hero, $copy['native']); diff --git a/tests/Feature/Landing/LandingTest.php b/tests/Feature/Landing/LandingTest.php index 28f2bdf2..7340eed4 100644 --- a/tests/Feature/Landing/LandingTest.php +++ b/tests/Feature/Landing/LandingTest.php @@ -25,6 +25,7 @@ function landingFamilies(): array 'landing.home' => ['Home', ['content.hero.title', 'engines.0.path', 'apiOrigin', 'iosEngines']], 'landing.download' => ['Download', ['content', 'mac', 'release', 'unreleased']], 'landing.ios' => ['Ios', ['content', 'ios', 'engines']], + 'landing.linux' => ['Linux', ['content', 'engines', 'links']], 'landing.pricing' => ['Pricing', ['content', 'apiOrigin', 'paidFeatures']], 'landing.teams' => ['Teams', ['content.header.title', 'content.seats.items', 'organizationProfiles']], 'landing.faq' => ['Faq', ['content', 'facts', 'platforms']], From 48361df90973401db6a3947bbbf7ce233396bce8 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Thu, 5 Nov 2026 15:06:02 +0700 Subject: [PATCH 2/3] docs(privacy): explain Linux usage data in every locale --- resources/data/legal/de/privacy.md | 28 +++++++++++++++++--- resources/data/legal/en/privacy.md | 28 +++++++++++++++++--- resources/data/legal/es/privacy.md | 28 +++++++++++++++++--- resources/data/legal/fr/privacy.md | 28 +++++++++++++++++--- resources/data/legal/id/privacy.md | 28 +++++++++++++++++--- resources/data/legal/it/privacy.md | 28 +++++++++++++++++--- resources/data/legal/ja/privacy.md | 28 +++++++++++++++++--- resources/data/legal/ko/privacy.md | 28 +++++++++++++++++--- resources/data/legal/pt-BR/privacy.md | 28 +++++++++++++++++--- resources/data/legal/vi/privacy.md | 28 +++++++++++++++++--- resources/data/legal/zh-Hans/privacy.md | 28 +++++++++++++++++--- resources/data/legal/zh-Hant/privacy.md | 28 +++++++++++++++++--- tests/Feature/Landing/LegalPagesTest.php | 11 ++++++-- tests/Feature/Localization/AppLabelsTest.php | 17 ++++++++++-- tests/Support/app-ui-labels.php | 2 ++ 15 files changed, 314 insertions(+), 52 deletions(-) diff --git a/resources/data/legal/de/privacy.md b/resources/data/legal/de/privacy.md index 2cf21bb1..287e3f17 100644 --- a/resources/data/legal/de/privacy.md +++ b/resources/data/legal/de/privacy.md @@ -1,14 +1,14 @@ --- title: Datenschutzerklärung description: Welche Daten die TablePro-Apps, die Website und das Kontoportal erfassen, wohin sie gehen, wie lange sie bleiben und wie du sie änderst oder löschst. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Diese Erklärung gilt für TablePro für Mac, TablePro für iPhone und iPad, die Website tablepro.app, die Dokumentation unter docs.tablepro.app und das Kontoportal account.tablepro.app. Sie beschreibt, was diese heute tatsächlich senden und speichern. Beide Apps sind quelloffen unter der AGPLv3. Den Code, der die unten genannten Daten sendet, kannst du im [TablePro-Repository]({github}) lesen. +Diese Erklärung gilt für TablePro für Mac, TablePro für Linux, TablePro für iPhone und iPad, die Website tablepro.app, die Dokumentation unter docs.tablepro.app und das Kontoportal account.tablepro.app. Sie beschreibt, was diese heute tatsächlich senden und speichern. Die Apps sind quelloffen unter der AGPLv3. Den Code, der die unten genannten Daten sendet, kannst du im [TablePro-Repository]({github}) lesen. ## Überblick {#summary} -- Die Mac-App sendet Nutzungsdaten. Dies ist standardmäßig aktiv und kann deaktiviert werden. Die iPhone- und iPad-App sendet einen Nutzungsbericht nur, wenn du es aktivierst. +- Die Mac-App sendet Nutzungsdaten. Dies ist standardmäßig aktiv und kann deaktiviert werden. Die iPhone- und iPad-App sendet einen Nutzungsbericht nur, wenn du es aktivierst. Die [Linux-App](#linux-usage-data) sendet Nutzungsdaten erst, wenn du Share wählst. - Wenn du dich bei einem TablePro-Konto anmeldest oder einen Lizenzschlüssel aktivierst, registriert die Mac-App deinen Mac samt Namen auf unserem Server und prüft dort regelmäßig deinen Tarif. - Deine Abfragen, Ergebnisse und Passwörter werden nicht an TablePro gesendet. Ausgenommen ist, was du in der Team Library veröffentlichst: Verbindungseinstellungen (niemals Passwörter) und gespeicherte Abfragen. - KI-Anfragen gehen von der Mac-App direkt an den von dir eingerichteten KI-Anbieter, nicht an uns. @@ -106,6 +106,26 @@ Die Mac-App sendet Daten an diese Dienste nur, wenn du sie einrichtest, und dire Passwörter werden im macOS-Schlüsselbund aufbewahrt. Deine Verbindungsliste, dein Abfrageverlauf, Query Insights, Data-Rewind-Snapshots, Einstellungen und offene Tabs werden auf deinem Mac gespeichert. Die App verweist auf SSH-Schlüssel an ihrem Speicherort und kopiert sie nicht. Versionen vor den TablePro-Konten enthalten weder einen Absturzmelder noch eine Analysebibliothek eines Drittanbieters. Ab der Version, die TablePro-Konten einführt, enthält die App die Bibliothek von PostHog, die die oben beschriebenen Nutzungsdaten sendet. Die Bibliothek enthält den Absturzmelder von PostHog, den die App ausgeschaltet lässt, sodass keine Absturzberichte gesendet werden. Sie speichert ihre zufällige ID, ihre Einstellungen und noch nicht gesendete Ereignisse in Dateien unter `~/Library/Application Support/com.TablePro`. +## Nutzungsdaten unter Linux {#linux-usage-data} + +**Es wird nichts gesendet, bis du Share wählst.** Mit deiner Einwilligung nutzt {publisherName} diese Daten, um die App-Nutzung, Kontoaktivitäten und Upgrade-Entscheidungen zu verstehen und Verbesserungen an TablePro zu planen. Du kannst die Freigabe unter **Preferences > General > Privacy > Share Usage Data** beenden. + +Solange die Freigabe aktiv ist, sendet die App ein Ereignis: + +- einmal pro lokalem Kalendertag, während sie läuft, mit den Datenbanktypen und der Anzahl offener Verbindungen; +- für den ersten Verbindungsversuch, die erste erfolgreiche Verbindung und die erste erfolgreiche Abfrage im Abfrageeditor, jeweils einmal pro Installation, mit dem Datenbanktyp. Ein Meilenstein bei ausgeschalteter Freigabe wird später nicht nachgesendet; +- bei jeder Anmeldung, mit der Anmeldemethode, und wenn du dich selbst abmeldest; +- bei jedem Klick auf Upgrade oder Buy a License, mit der Stelle, an der du geklickt hast; +- wenn der Lizenzhinweis erscheint und wenn du ihn mit Buy a License beantwortest. Die Anzahl deiner Nutzungstage bleibt auf deinem Computer. + +Vor der Anmeldung tragen Ereignisse eine zufällige Installations-ID. Nach der Anmeldung tragen sie stattdessen deine Konto-ID und verknüpfen frühere Aktivitäten mit diesem Konto. Dessen PostHog-Profil enthält die App- und Betriebssystemversion, die Prozessorarchitektur und die Sprache der Oberfläche. Beim Abmelden wird eine neue zufällige ID erzeugt. + +Ereignisse gehen direkt an PostHog, unseren Auftragsverarbeiter für Produktanalysen, unter `eu.i.posthog.com` in dessen EU-Cloud. Jedes Ereignis enthält auch den Namen und die Version des Betriebssystems, die Version der Analysebibliothek, eine Ereignis-ID und die Zeit. PostHog sieht deine IP-Adresse und leitet daraus einen ungefähren Standort ab, etwa Land und Stadt. Siehe [Internationale Übermittlungen](#transfers). + +Diese Ereignisse enthalten niemals Datenbank-Hostnamen, Zugangsdaten, SQL-Text oder Zeileninhalte. Das Ereignis zur ersten Abfrage erfasst nur deren Erfolg und den Datenbanktyp, nicht die Abfrage selbst. + +Das Ausschalten widerruft deine Einwilligung und stoppt künftige Sendungen, auch wartende Ereignisse. Eine bereits übertragene Anfrage kann noch ankommen. Bereits empfangene Daten werden dadurch nicht gelöscht. Wir haben [keine Speicherfrist für diese Ereignisse festgelegt](#retention). Für Auskunft oder Löschung siehe [Deine Rechte](#rights) oder schreibe an [{email}](mailto:{email}). + ## TablePro für iPhone und iPad {#ios-app} **Nichts geht an TablePro, solange du „Share Usage Data“ nicht aktivierst**, beim ersten Start oder später unter **Settings > Privacy**. Wenn du es aktivierst, sendet die App einmal täglich einen Bericht an denselben Server wie die Versionen der Mac-App vor den TablePro-Konten. Unser Server leitet ihn auf dieselbe Weise an PostHog weiter, ohne seine IP-Adresse. Der Bericht enthält einen SHA-256-Hash der Kennung, die Apple der App auf deinem Gerät zuweist, Plattform, App- und iOS-Version, Prozessorarchitektur, App-Sprache, Namen der Datenbanktypen deiner geöffneten Verbindungen, deren Anzahl sowie Datum und Uhrzeit deines ersten Verbindungsversuchs, deiner ersten erfolgreichen Verbindung und deiner ersten Abfrage. Er enthält keine Update-Einstellungen und meldet immer, dass keine Lizenz aktiviert ist, da die App beides nicht hat. @@ -207,7 +227,7 @@ Für Leser im Europäischen Wirtschaftsraum und im Vereinigten Königreich sind - **Vertrag** (Art. 6 Abs. 1 lit. b): Verkauf und Bereitstellung einer Lizenz, dein Konto mit Anmeldemethoden und Geräten, Lizenzprüfungen, Kontoportal und Team Library. - **Berechtigtes Interesse** (Art. 6 Abs. 1 lit. f): Nutzungsdaten der Mac-App und ihre Auswertung in PostHog, die Ereignisse zu Anmeldungen, Käufen, Geräten und Teams, die unser Server an PostHog sendet, Audit-Log des Kontos, Sicherheit und Missbrauchsprävention einschließlich Cloudflare Turnstile im Newsletter-Formular, Serverprotokolle, Cloudflare Web Analytics, Kaufzuordnungsdatensatz, Länderabfrage für Sprache und regionalen Rabatt sowie Live-Chat auf jeder Seite. -- **Einwilligung** (Art. 6 Abs. 1 lit. a): Google-Analytics-Cookies, Nutzungsbericht der iPhone- und iPad-App, Newsletter und von dir begonnene Live-Chat-Gespräche. +- **Einwilligung** (Art. 6 Abs. 1 lit. a): Nutzungsdaten der Linux-App, Google-Analytics-Cookies, Nutzungsbericht der iPhone- und iPad-App, Newsletter und von dir begonnene Live-Chat-Gespräche. - **Gesetzliche Verpflichtung** (Art. 6 Abs. 1 lit. c): Steuer- und Buchhaltungsunterlagen sowie Antworten auf rechtmäßige Anfragen. ## Wer Daten erhält {#sharing} diff --git a/resources/data/legal/en/privacy.md b/resources/data/legal/en/privacy.md index adadad63..faea57f8 100644 --- a/resources/data/legal/en/privacy.md +++ b/resources/data/legal/en/privacy.md @@ -1,14 +1,14 @@ --- title: Privacy policy description: What TablePro's apps, website and account portal collect, where it goes, how long it is kept, and how to change or delete it. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -This policy covers TablePro for Mac, TablePro for iPhone and iPad, the website at tablepro.app, the documentation at docs.tablepro.app, and the account portal at account.tablepro.app. It describes what each of them actually sends and stores today. Both apps are open source under the AGPLv3, so you can read the code that sends any of the data below in the [TablePro repository]({github}). +This policy covers TablePro for Mac, TablePro for Linux, TablePro for iPhone and iPad, the website at tablepro.app, the documentation at docs.tablepro.app, and the account portal at account.tablepro.app. It describes what each of them actually sends and stores today. The apps are open source under the AGPLv3, so you can read the code that sends any of the data below in the [TablePro repository]({github}). ## Summary {#summary} -- The Mac app sends usage data. It is on by default and you can turn it off. The iPhone and iPad app sends a usage report only if you turn it on. +- The Mac app sends usage data. It is on by default and you can turn it off. The iPhone and iPad app sends a usage report only if you turn it on. The [Linux app](#linux-usage-data) sends usage data only after you choose Share. - If you sign in to a TablePro account or activate a license key, the Mac app registers your Mac with our server, including its name, and checks your plan with it regularly. - The queries you run, your results and your passwords are not sent to TablePro. The exception is what you choose to publish to a Team Library: connection settings (never passwords) and saved queries. - AI requests go from the Mac app directly to the AI provider you set up, not to us. @@ -106,6 +106,26 @@ The Mac app sends data to these services only when you set them up, and directly Passwords are kept in the macOS Keychain. Your connection list, query history, Query Insights, Data Rewind snapshots, settings and open tabs are stored on your Mac. The app references SSH keys where they are on disk and does not copy them. Versions before TablePro accounts contain no crash reporter and no third-party analytics library. From the version that adds TablePro accounts, the app includes PostHog's library, which sends the usage data described above. The library contains PostHog's crash reporter, which the app leaves turned off, so it sends no crash reports. The library keeps its random ID, its settings and any events not sent yet in files under `~/Library/Application Support/com.TablePro`. +## Linux usage data {#linux-usage-data} + +**Nothing is sent until you choose Share.** With your consent, {publisherName} uses this data to understand app use, account activity and upgrade choices, and decide what to improve in TablePro. You can stop sharing in **Preferences > General > Privacy > Share Usage Data**. + +While sharing is on, the app sends an event: + +- once per local day while it runs, with the database types and number of open connections; +- for the first connection attempt, first successful connection and first successful query in the query editor, each once per installation, with the database type. A milestone reached while sharing is off is never sent later; +- each time you sign in, with the sign-in method, and each time you choose to sign out; +- each time you click Upgrade or Buy a License, with where you clicked; +- each time the license prompt appears and when you answer it with Buy a License. The number of days you have used the app stays on your computer. + +Before sign-in, events carry a random installation ID. After sign-in, they carry your account ID instead, linking earlier activity to that account. Its PostHog profile holds the app and OS versions, processor architecture and interface language. Signing out starts a new random ID. + +Events go directly to PostHog, our processor for product analytics, at `eu.i.posthog.com` in its EU cloud. Each event also carries the OS name and version, analytics library version, an event ID and time. PostHog sees your IP address and derives an approximate location, such as country and city. See [International transfers](#transfers). + +These events never contain database host names, credentials, SQL text or row contents. The first-query event records that a query succeeded and its database type, not the query itself. + +Turning sharing off withdraws consent and stops future sending, including queued events. A request already in transit may still arrive. It does not erase data already received. We have [not set a time limit for these events](#retention). For access or deletion, see [Your rights](#rights) or email [{email}](mailto:{email}). + ## TablePro for iPhone and iPad {#ios-app} **Nothing goes to TablePro unless you turn on Share Usage Data**, when the app first starts or later in **Settings > Privacy**. If you do, the app sends a report once a day to the same server as Mac versions before TablePro accounts, which passes it on to PostHog in the same way, without its IP address. The report contains a SHA-256 hash of the identifier Apple gives the app on your device, the platform, the app and iOS versions, the processor architecture, the app's language, the names of the database types of your open connections, how many are open, and the date and time of your first connection attempt, your first successful connection and your first query. It carries no update settings and always reports that no license is activated, because the app has neither. @@ -207,7 +227,7 @@ For readers in the European Economic Area and the United Kingdom, the lawful bas - **Contract** (Art. 6(1)(b)): selling and providing a license, your account with its sign-in methods and devices, license checks, the account portal and the Team Library. - **Legitimate interest** (Art. 6(1)(f)): the Mac app's usage data and its analysis in PostHog, the events about sign-ins, purchases, devices and teams our server sends to PostHog, the account's audit log, security and abuse prevention, including Cloudflare Turnstile on the newsletter form, server logs, Cloudflare Web Analytics, the purchase attribution record, the country lookups for the language bar and the regional discount, and the live chat on every page. -- **Consent** (Art. 6(1)(a)): Google Analytics cookies, the iPhone and iPad app's usage report, the newsletter and the conversations you start in live chat. +- **Consent** (Art. 6(1)(a)): the Linux app's usage data, Google Analytics cookies, the iPhone and iPad app's usage report, the newsletter and the conversations you start in live chat. - **Legal obligation** (Art. 6(1)(c)): tax and accounting records, and answers to lawful requests. ## Who receives data {#sharing} diff --git a/resources/data/legal/es/privacy.md b/resources/data/legal/es/privacy.md index df347381..b5501c7c 100644 --- a/resources/data/legal/es/privacy.md +++ b/resources/data/legal/es/privacy.md @@ -1,14 +1,14 @@ --- title: Política de privacidad description: Qué recopilan las apps, el sitio web y el portal de cuentas de TablePro, adónde se envía, cuánto tiempo se conserva y cómo modificarlo o eliminarlo. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Esta política cubre TablePro para Mac, TablePro para iPhone y iPad, el sitio web tablepro.app, la documentación en docs.tablepro.app y el portal de cuentas account.tablepro.app. Describe qué envía y almacena realmente cada uno de ellos en la actualidad. Ambas apps son de código abierto bajo AGPLv3, por lo que puedes consultar el código que envía cualquiera de los datos siguientes en el [repositorio de TablePro]({github}). +Esta política cubre TablePro para Mac, TablePro para Linux, TablePro para iPhone y iPad, el sitio web tablepro.app, la documentación en docs.tablepro.app y el portal de cuentas account.tablepro.app. Describe qué envía y almacena realmente cada uno de ellos en la actualidad. Las apps son de código abierto bajo AGPLv3, por lo que puedes consultar el código que envía cualquiera de los datos siguientes en el [repositorio de TablePro]({github}). ## Resumen {#summary} -- La app para Mac envía datos de uso. Está activado por defecto y puedes desactivarlo. La app para iPhone y iPad solo envía un informe de uso si lo activas. +- La app para Mac envía datos de uso. Está activado por defecto y puedes desactivarlo. La app para iPhone y iPad solo envía un informe de uso si lo activas. La [app para Linux](#linux-usage-data) solo envía datos de uso después de que elijas Share. - Si inicias sesión en una cuenta de TablePro o activas una clave de licencia, la app para Mac registra tu Mac en nuestro servidor, con su nombre, y comprueba tu plan con él periódicamente. - Las consultas que ejecutas, tus resultados y tus contraseñas no se envían a TablePro. La excepción es lo que decidas publicar en Team Library: ajustes de conexión (nunca contraseñas) y consultas guardadas. - Las solicitudes de IA van directamente desde la app para Mac al proveedor de IA que configures, no a nosotros. @@ -106,6 +106,26 @@ La app para Mac solo envía datos a estos servicios cuando los configuras, direc Las contraseñas se guardan en el Llavero de macOS. La lista de conexiones, el historial de consultas, Query Insights, las instantáneas de Data Rewind, los ajustes y las pestañas abiertas se almacenan en tu Mac. La app referencia las claves SSH donde están en el disco y no las copia. Las versiones anteriores a las cuentas de TablePro no contienen un sistema de informes de fallos ni una biblioteca de análisis de terceros. A partir de la versión que añade las cuentas de TablePro, la app incluye la biblioteca de PostHog, que envía los datos de uso descritos arriba. La biblioteca contiene el sistema de informes de fallos de PostHog, que la app deja desactivado, así que no envía informes de fallos. La biblioteca guarda su identificador aleatorio, su configuración y los eventos aún no enviados en archivos dentro de `~/Library/Application Support/com.TablePro`. +## Datos de uso en Linux {#linux-usage-data} + +**No se envía nada hasta que elijas Share.** Con tu consentimiento, {publisherName} usa estos datos para entender el uso de la app, la actividad de las cuentas y las decisiones de actualización, y decidir qué mejorar en TablePro. Puedes dejar de compartir en **Preferences > General > Privacy > Share Usage Data**. + +Mientras compartes datos, la app envía un evento: + +- una vez por día local mientras se ejecuta, con los tipos de bases de datos y el número de conexiones abiertas; +- por el primer intento de conexión, la primera conexión correcta y la primera consulta correcta en el editor, cada uno una vez por instalación, con el tipo de base de datos. Un hito alcanzado con el envío desactivado no se envía después; +- cada vez que inicias sesión, con el método de acceso, y cada vez que eliges cerrar sesión; +- cada vez que pulsas Upgrade o Buy a License, con el lugar donde pulsaste; +- cada vez que aparece el aviso de compra de licencia y cuando respondes con Buy a License. El número de días que has usado la app permanece en tu equipo. + +Antes de iniciar sesión, los eventos llevan un ID de instalación aleatorio. Después llevan el ID de tu cuenta, lo que vincula la actividad anterior a ella. Su perfil en PostHog guarda las versiones de la app y del sistema operativo, la arquitectura del procesador y el idioma de la interfaz. Cerrar sesión genera un nuevo ID aleatorio. + +Los eventos van directamente a PostHog, nuestro encargado del tratamiento para el análisis del producto, en `eu.i.posthog.com`, en su nube de la UE. Cada evento también lleva el nombre y la versión del sistema operativo, la versión de la biblioteca de análisis, un ID de evento y la hora. PostHog ve tu dirección IP y deduce una ubicación aproximada, como el país y la ciudad. Consulta [Transferencias internacionales](#transfers). + +Estos eventos nunca contienen nombres de host de bases de datos, credenciales, texto SQL ni contenido de filas. El evento de primera consulta registra que una consulta se completó y el tipo de base de datos, no la consulta en sí. + +Desactivar el envío retira tu consentimiento y detiene los envíos futuros, incluidos los eventos en cola. Una solicitud que ya esté en tránsito aún puede llegar. No borra los datos ya recibidos. [No hemos fijado un plazo de conservación para estos eventos](#retention). Para acceder a ellos o borrarlos, consulta [Tus derechos](#rights) o escribe a [{email}](mailto:{email}). + ## TablePro para iPhone y iPad {#ios-app} **No se envía nada a TablePro a menos que actives Share Usage Data**, al iniciar la app por primera vez o después en **Settings > Privacy**. Si lo haces, la app envía un informe una vez al día al mismo servidor que las versiones de la app para Mac anteriores a las cuentas de TablePro, y nuestro servidor lo reenvía a PostHog de la misma forma, sin su dirección IP. El informe contiene un hash SHA-256 del identificador que Apple asigna a la app en tu dispositivo, la plataforma, las versiones de la app y de iOS, la arquitectura del procesador, el idioma de la app, los nombres de los tipos de bases de datos de tus conexiones abiertas, cuántas hay abiertas, y la fecha y la hora del primer intento de conexión, de la primera conexión correcta y de la primera consulta. No incluye ajustes de actualización y siempre indica que no hay ninguna licencia activada, porque la app no tiene ni lo uno ni lo otro. @@ -207,7 +227,7 @@ Para lectores del Espacio Económico Europeo y del Reino Unido, las bases juríd - **Contrato** (art. 6.1.b): venta y provisión de licencias, tu cuenta con sus métodos de inicio de sesión y dispositivos, comprobaciones de licencia, portal de cuentas y Team Library. - **Interés legítimo** (art. 6.1.f): datos de uso de la app para Mac y su análisis en PostHog, eventos sobre inicios de sesión, compras, dispositivos y equipos que nuestro servidor envía a PostHog, registro de auditoría de la cuenta, seguridad y prevención de abusos, incluido Cloudflare Turnstile en el formulario del boletín, registros del servidor, Cloudflare Web Analytics, registro de atribución de compras, consulta de país para el idioma y el descuento regional, y chat en directo en todas las páginas. -- **Consentimiento** (art. 6.1.a): cookies de Google Analytics, informe de uso de la app para iPhone y iPad, boletín y conversaciones que inicias en el chat en directo. +- **Consentimiento** (art. 6.1.a): datos de uso de la app para Linux, cookies de Google Analytics, informe de uso de la app para iPhone y iPad, boletín y conversaciones que inicias en el chat en directo. - **Obligación legal** (art. 6.1.c): registros fiscales y contables y respuestas a solicitudes legítimas. ## Quién recibe datos {#sharing} diff --git a/resources/data/legal/fr/privacy.md b/resources/data/legal/fr/privacy.md index 50b64373..90f6190e 100644 --- a/resources/data/legal/fr/privacy.md +++ b/resources/data/legal/fr/privacy.md @@ -1,14 +1,14 @@ --- title: Politique de confidentialité description: Ce que collectent les apps, le site et le portail de comptes TablePro, où vont ces données, leur durée de conservation, comment les modifier ou supprimer. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Cette politique couvre TablePro pour Mac, TablePro pour iPhone et iPad, le site web tablepro.app, la documentation sur docs.tablepro.app et le portail de comptes account.tablepro.app. Elle décrit ce que chacun envoie et stocke réellement aujourd’hui. Les deux applications sont open source sous AGPLv3 ; vous pouvez donc lire le code qui envoie les données ci-dessous dans le [dépôt TablePro]({github}). +Cette politique couvre TablePro pour Mac, TablePro pour Linux, TablePro pour iPhone et iPad, le site web tablepro.app, la documentation sur docs.tablepro.app et le portail de comptes account.tablepro.app. Elle décrit ce que chacun envoie et stocke réellement aujourd’hui. Les applications sont open source sous AGPLv3 ; vous pouvez donc lire le code qui envoie les données ci-dessous dans le [dépôt TablePro]({github}). ## Résumé {#summary} -- L’application Mac envoie des données d’utilisation. Cet envoi est activé par défaut et vous pouvez le désactiver. L’application iPhone et iPad n’envoie de rapport d’utilisation que si vous l’activez. +- L’application Mac envoie des données d’utilisation. Cet envoi est activé par défaut et vous pouvez le désactiver. L’application iPhone et iPad n’envoie de rapport d’utilisation que si vous l’activez. L’[application Linux](#linux-usage-data) n’envoie des données d’utilisation qu’après votre choix de Share. - Si vous vous connectez à un compte TablePro ou activez une clé de licence, l’application Mac enregistre votre Mac sur notre serveur, avec son nom, et y vérifie régulièrement votre offre. - Vos requêtes, résultats et mots de passe ne sont pas envoyés à TablePro. L’exception concerne ce que vous choisissez de publier dans Team Library : paramètres de connexion (jamais les mots de passe) et requêtes enregistrées. - Les demandes IA vont directement de l’application Mac au fournisseur IA que vous avez configuré, pas à nous. @@ -106,6 +106,26 @@ L’application Mac n’envoie des données à ces services que lorsque vous les Les mots de passe sont conservés dans le Trousseau macOS. Votre liste de connexions, l’historique des requêtes, Query Insights, les instantanés Data Rewind, les réglages et les onglets ouverts sont stockés sur votre Mac. L’application référence les clés SSH à leur emplacement sur le disque sans les copier. Les versions antérieures aux comptes TablePro ne contiennent aucun outil de rapport de plantage ni bibliothèque d’analyse tierce. À partir de la version qui ajoute les comptes TablePro, l’application inclut la bibliothèque de PostHog, qui envoie les données d’utilisation décrites ci-dessus. La bibliothèque contient l’outil de rapport de plantage de PostHog, que l’application laisse désactivé, si bien qu’aucun rapport de plantage n’est envoyé. Elle conserve son identifiant aléatoire, ses paramètres et les événements pas encore envoyés dans des fichiers sous `~/Library/Application Support/com.TablePro`. +## Données d’utilisation sous Linux {#linux-usage-data} + +**Rien n’est envoyé tant que vous ne choisissez pas Share.** Avec votre consentement, {publisherName} utilise ces données pour comprendre l’usage de l’application, l’activité des comptes et les choix de mise à niveau, puis décider quoi améliorer dans TablePro. Vous pouvez arrêter le partage dans **Preferences > General > Privacy > Share Usage Data**. + +Quand le partage est activé, l’application envoie un événement : + +- une fois par jour local pendant son exécution, avec les types de bases de données et le nombre de connexions ouvertes ; +- pour la première tentative de connexion, la première connexion réussie et la première requête réussie dans l’éditeur, chacune une fois par installation, avec le type de base de données. Une étape atteinte quand le partage est désactivé n’est jamais envoyée plus tard ; +- à chaque connexion au compte, avec la méthode de connexion, et chaque fois que vous choisissez de vous déconnecter ; +- à chaque clic sur Upgrade ou Buy a License, avec l’endroit du clic ; +- chaque fois que le rappel d’achat de licence apparaît et quand vous y répondez par Buy a License. Le nombre de jours d’utilisation reste sur votre ordinateur. + +Avant la connexion au compte, les événements portent un identifiant d’installation aléatoire. Après, ils portent celui du compte, ce qui lui associe l’activité antérieure. Son profil PostHog contient les versions de l’application et du système, l’architecture du processeur et la langue de l’interface. La déconnexion crée un nouvel identifiant aléatoire. + +Les événements vont directement à PostHog, notre sous-traitant pour l’analyse du produit, sur `eu.i.posthog.com`, dans son cloud européen. Chaque événement contient aussi le nom et la version du système, la version de la bibliothèque d’analyse, un identifiant d’événement et l’heure. PostHog voit votre adresse IP et en déduit une localisation approximative, comme le pays et la ville. Voir [Transferts internationaux](#transfers). + +Ces événements ne contiennent jamais de noms d’hôtes de bases de données, d’identifiants de connexion, de texte SQL ni de contenu de lignes. L’événement de première requête indique sa réussite et le type de base de données, pas la requête elle-même. + +Désactiver le partage retire votre consentement et arrête les envois futurs, y compris les événements en attente. Une requête déjà en transit peut encore arriver. Cela n’efface pas les données déjà reçues. Nous n’avons [pas fixé de durée de conservation pour ces événements](#retention). Pour y accéder ou les supprimer, voir [Vos droits](#rights) ou écrire à [{email}](mailto:{email}). + ## TablePro pour iPhone et iPad {#ios-app} **Rien n’est envoyé à TablePro tant que vous n’activez pas Share Usage Data**, au premier démarrage ou plus tard dans **Settings > Privacy**. Si vous le faites, l’application envoie un rapport une fois par jour au même serveur que les versions de l’application Mac antérieures aux comptes TablePro, et notre serveur le transmet à PostHog de la même manière, sans son adresse IP. Le rapport contient un hachage SHA-256 de l’identifiant donné par Apple à l’application sur votre appareil, la plateforme, les versions de l’application et d’iOS, l’architecture du processeur, la langue de l’application, les noms des types de bases de vos connexions ouvertes, le nombre de connexions ouvertes, ainsi que la date et l’heure de votre première tentative de connexion, de votre première connexion réussie et de votre première requête. Il ne contient aucun réglage de mise à jour et indique toujours qu’aucune licence n’est activée, car l’application n’a ni l’un ni l’autre. @@ -207,7 +227,7 @@ Pour les lecteurs de l’Espace économique européen et du Royaume-Uni, les bas - **Contrat** (art. 6(1)(b)) : vente et fourniture d’une licence, votre compte avec ses méthodes de connexion et ses appareils, vérifications de licence, portail de comptes et Team Library. - **Intérêt légitime** (art. 6(1)(f)) : données d’utilisation de l’application Mac et leur analyse dans PostHog, événements sur les connexions, achats, appareils et équipes que notre serveur envoie à PostHog, journal d’audit du compte, sécurité et prévention des abus, y compris Cloudflare Turnstile sur le formulaire de newsletter, journaux du serveur, Cloudflare Web Analytics, enregistrement d’attribution des achats, recherche du pays pour la langue et la réduction régionale, et chat sur chaque page. -- **Consentement** (art. 6(1)(a)) : cookies Google Analytics, rapport d’utilisation iPhone et iPad, newsletter et conversations initiées dans le chat. +- **Consentement** (art. 6(1)(a)) : données d’utilisation de l’application Linux, cookies Google Analytics, rapport d’utilisation iPhone et iPad, newsletter et conversations initiées dans le chat. - **Obligation légale** (art. 6(1)(c)) : documents fiscaux et comptables et réponses aux demandes légales. ## Qui reçoit les données {#sharing} diff --git a/resources/data/legal/id/privacy.md b/resources/data/legal/id/privacy.md index 92e957c9..9fb6251f 100644 --- a/resources/data/legal/id/privacy.md +++ b/resources/data/legal/id/privacy.md @@ -1,14 +1,14 @@ --- title: Kebijakan privasi description: Data yang dikumpulkan aplikasi, situs web, dan portal akun TablePro, tujuan pengirimannya, lama penyimpanannya, serta cara mengubah atau menghapusnya. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Kebijakan ini mencakup TablePro untuk Mac, TablePro untuk iPhone dan iPad, situs web di tablepro.app, dokumentasi di docs.tablepro.app, dan portal akun di account.tablepro.app. Kebijakan ini menjelaskan data yang benar-benar dikirim dan disimpan oleh masing-masing layanan saat ini. Kedua aplikasi bersifat sumber terbuka dengan lisensi AGPLv3, sehingga Anda dapat membaca kode yang mengirim data di bawah ini dalam [repositori TablePro]({github}). +Kebijakan ini mencakup TablePro untuk Mac, TablePro untuk Linux, TablePro untuk iPhone dan iPad, situs web di tablepro.app, dokumentasi di docs.tablepro.app, dan portal akun di account.tablepro.app. Kebijakan ini menjelaskan data yang benar-benar dikirim dan disimpan oleh masing-masing layanan saat ini. Aplikasi-aplikasi ini bersifat sumber terbuka dengan lisensi AGPLv3, sehingga Anda dapat membaca kode yang mengirim data di bawah ini dalam [repositori TablePro]({github}). ## Ringkasan {#summary} -- Aplikasi Mac mengirim data penggunaan. Fitur ini aktif secara bawaan dan dapat Anda nonaktifkan. Aplikasi iPhone dan iPad hanya mengirim laporan penggunaan jika Anda mengaktifkannya. +- Aplikasi Mac mengirim data penggunaan. Fitur ini aktif secara bawaan dan dapat Anda nonaktifkan. Aplikasi iPhone dan iPad hanya mengirim laporan penggunaan jika Anda mengaktifkannya. [Aplikasi Linux](#linux-usage-data) hanya mengirim data penggunaan setelah Anda memilih Share. - Jika Anda masuk ke akun TablePro atau mengaktifkan kunci lisensi, aplikasi Mac mendaftarkan Mac Anda di server kami, termasuk namanya, dan memeriksa paket Anda secara berkala. - Kueri yang Anda jalankan, hasilnya, dan kata sandi Anda tidak dikirim ke TablePro. Pengecualiannya adalah data yang Anda pilih untuk dipublikasikan ke Team Library: pengaturan koneksi (tanpa kata sandi) dan kueri tersimpan. - Permintaan AI dikirim langsung dari aplikasi Mac ke penyedia AI yang Anda konfigurasikan, bukan kepada kami. @@ -106,6 +106,26 @@ Aplikasi Mac hanya mengirim data ke layanan berikut saat Anda mengonfigurasikann Kata sandi disimpan di Rantai Kunci macOS. Daftar koneksi, riwayat kueri, Query Insights, snapshot Data Rewind, pengaturan, dan tab terbuka disimpan di Mac Anda. Aplikasi merujuk kunci SSH di lokasi aslinya pada disk dan tidak menyalinnya. Versi sebelum akun TablePro tidak berisi pelapor kerusakan atau pustaka analitik pihak ketiga. Mulai versi yang menghadirkan akun TablePro, aplikasi menyertakan pustaka PostHog, yang mengirim data penggunaan yang dijelaskan di atas. Pustaka itu berisi pelapor kerusakan PostHog, yang dibiarkan nonaktif oleh aplikasi, sehingga tidak ada laporan kerusakan yang dikirim. Pustaka menyimpan ID acaknya, pengaturannya, dan peristiwa yang belum terkirim dalam file di bawah `~/Library/Application Support/com.TablePro`. +## Data penggunaan di Linux {#linux-usage-data} + +**Tidak ada data yang dikirim sampai Anda memilih Share.** Dengan persetujuan Anda, {publisherName} menggunakan data ini untuk memahami penggunaan aplikasi, aktivitas akun, dan pilihan peningkatan paket, lalu menentukan perbaikan untuk TablePro. Anda dapat berhenti berbagi di **Preferences > General > Privacy > Share Usage Data**. + +Saat berbagi diaktifkan, aplikasi mengirim peristiwa: + +- sekali per hari menurut waktu setempat saat aplikasi berjalan, dengan jenis database dan jumlah koneksi terbuka; +- untuk percobaan koneksi pertama, koneksi pertama yang berhasil, dan kueri pertama yang berhasil di editor, masing-masing sekali per instalasi, dengan jenis database. Pencapaian saat berbagi dinonaktifkan tidak pernah dikirim kemudian; +- setiap kali Anda masuk, dengan metode masuk, dan setiap kali Anda memilih keluar dari akun; +- setiap kali Anda mengklik Upgrade atau Buy a License, dengan lokasi klik; +- setiap kali ajakan membeli lisensi muncul dan saat Anda menjawab dengan Buy a License. Jumlah hari penggunaan aplikasi tetap tersimpan di komputer Anda. + +Sebelum masuk, peristiwa membawa ID instalasi acak. Setelah masuk, peristiwa membawa ID akun Anda, yang menghubungkan aktivitas sebelumnya dengan akun itu. Profil PostHog akun menyimpan versi aplikasi dan sistem operasi, arsitektur prosesor, dan bahasa antarmuka. Keluar dari akun membuat ID acak baru. + +Peristiwa langsung dikirim ke PostHog, pemroses data kami untuk analisis produk, di `eu.i.posthog.com` pada cloud Uni Eropanya. Setiap peristiwa juga membawa nama dan versi sistem operasi, versi pustaka analisis, ID peristiwa, dan waktu. PostHog melihat alamat IP Anda dan memperkirakan lokasi, seperti negara dan kota. Lihat [Transfer internasional](#transfers). + +Peristiwa ini tidak pernah berisi nama host database, kredensial, teks SQL, atau isi baris. Peristiwa kueri pertama mencatat bahwa kueri berhasil dan jenis database, bukan kuerinya. + +Menonaktifkan berbagi menarik persetujuan Anda dan menghentikan pengiriman berikutnya, termasuk peristiwa dalam antrean. Permintaan yang sudah dalam perjalanan masih dapat tiba. Ini tidak menghapus data yang sudah diterima. Kami [belum menetapkan batas waktu penyimpanan peristiwa ini](#retention). Untuk mengakses atau menghapus data, lihat [Hak Anda](#rights) atau kirim email ke [{email}](mailto:{email}). + ## TablePro untuk iPhone dan iPad {#ios-app} **Tidak ada data yang dikirim ke TablePro kecuali Anda mengaktifkan Share Usage Data**, saat aplikasi pertama kali dimulai atau kemudian di **Settings > Privacy**. Jika diaktifkan, aplikasi mengirim laporan sekali sehari ke server yang sama dengan versi aplikasi Mac sebelum akun TablePro, dan server kami meneruskannya ke PostHog dengan cara yang sama, tanpa alamat IP-nya. Laporan berisi hash SHA-256 dari pengenal yang diberikan Apple kepada aplikasi di perangkat Anda, platform, versi aplikasi dan iOS, arsitektur prosesor, bahasa aplikasi, nama jenis database dari koneksi yang sedang terbuka, jumlah koneksi yang terbuka, serta tanggal dan waktu percobaan koneksi pertama, koneksi pertama yang berhasil, dan kueri pertama. Laporan tidak berisi pengaturan pembaruan dan selalu menyatakan tidak ada lisensi yang diaktifkan karena aplikasi tidak memiliki keduanya. @@ -207,7 +227,7 @@ Bagi pembaca di Wilayah Ekonomi Eropa dan Britania Raya, dasar hukum berdasarkan - **Kontrak** (Art. 6(1)(b)): penjualan dan penyediaan lisensi, akun Anda beserta metode masuk dan perangkatnya, pemeriksaan lisensi, portal akun, dan Team Library. - **Kepentingan yang sah** (Art. 6(1)(f)): data penggunaan aplikasi Mac dan analisisnya di PostHog, peristiwa tentang proses masuk, pembelian, perangkat, dan tim yang dikirim server kami ke PostHog, log audit akun, keamanan dan pencegahan penyalahgunaan, termasuk Cloudflare Turnstile pada formulir buletin, log server, Cloudflare Web Analytics, catatan atribusi pembelian, pencarian negara untuk bahasa dan diskon regional, dan chat langsung di setiap halaman. -- **Persetujuan** (Art. 6(1)(a)): cookie Google Analytics, laporan penggunaan aplikasi iPhone dan iPad, buletin, serta percakapan yang Anda mulai melalui chat langsung. +- **Persetujuan** (Art. 6(1)(a)): data penggunaan aplikasi Linux, cookie Google Analytics, laporan penggunaan aplikasi iPhone dan iPad, buletin, serta percakapan yang Anda mulai melalui chat langsung. - **Kewajiban hukum** (Art. 6(1)(c)): catatan pajak dan akuntansi, serta jawaban atas permintaan yang sah menurut hukum. ## Penerima data {#sharing} diff --git a/resources/data/legal/it/privacy.md b/resources/data/legal/it/privacy.md index 1e64a128..1dc7f8e0 100644 --- a/resources/data/legal/it/privacy.md +++ b/resources/data/legal/it/privacy.md @@ -1,14 +1,14 @@ --- title: Informativa sulla privacy description: Quali dati raccolgono le app, il sito web e il portale account di TablePro, dove vanno, per quanto tempo restano e come modificarli o eliminarli. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Questa informativa riguarda TablePro per Mac, TablePro per iPhone e iPad, il sito web tablepro.app, la documentazione su docs.tablepro.app e il portale account account.tablepro.app. Descrive quali dati ciascuno di essi invia e conserva effettivamente oggi. Entrambe le app sono open source con licenza AGPLv3: puoi quindi leggere il codice che invia i dati descritti di seguito nel [repository di TablePro]({github}). +Questa informativa riguarda TablePro per Mac, TablePro per Linux, TablePro per iPhone e iPad, il sito web tablepro.app, la documentazione su docs.tablepro.app e il portale account account.tablepro.app. Descrive quali dati ciascuno di essi invia e conserva effettivamente oggi. Le app sono open source con licenza AGPLv3: puoi quindi leggere il codice che invia i dati descritti di seguito nel [repository di TablePro]({github}). ## Riepilogo {#summary} -- L'app per Mac invia dati di utilizzo. L'invio è attivo per impostazione predefinita e puoi disattivarlo. L'app per iPhone e iPad invia un rapporto sull'utilizzo solo se lo attivi. +- L'app per Mac invia dati di utilizzo. L'invio è attivo per impostazione predefinita e puoi disattivarlo. L'app per iPhone e iPad invia un rapporto sull'utilizzo solo se lo attivi. L’[app per Linux](#linux-usage-data) invia dati di utilizzo solo dopo che scegli Share. - Se accedi a un account TablePro o attivi una chiave di licenza, l'app per Mac registra il tuo Mac sul nostro server, con il suo nome, e verifica regolarmente il tuo piano. - Le query che esegui, i risultati e le password non vengono inviati a TablePro. Fa eccezione ciò che scegli di pubblicare nella Team Library: impostazioni delle connessioni (mai le password) e query salvate. - Le richieste di IA vengono inviate direttamente dall'app per Mac al fornitore di IA che configuri, non a noi. @@ -106,6 +106,26 @@ L'app per Mac invia dati a questi servizi solo quando li configuri, direttamente Le password sono conservate nel Portachiavi di macOS. L'elenco delle connessioni, la cronologia delle query, Query Insights, le istantanee di Data Rewind, le impostazioni e le schede aperte sono conservati sul Mac. L'app fa riferimento alle chiavi SSH nella loro posizione sul disco e non le copia. Le versioni precedenti agli account TablePro non contengono un sistema di segnalazione degli arresti anomali né una libreria di analisi di terze parti. Dalla versione che introduce gli account TablePro, l'app include la libreria di PostHog, che invia i dati di utilizzo descritti sopra. La libreria contiene il sistema di segnalazione degli arresti anomali di PostHog, che l'app lascia disattivato, quindi non viene inviata alcuna segnalazione. La libreria conserva il suo ID casuale, le sue impostazioni e gli eventi non ancora inviati in file sotto `~/Library/Application Support/com.TablePro`. +## Dati di utilizzo su Linux {#linux-usage-data} + +**Non viene inviato nulla finché non scegli Share.** Con il tuo consenso, {publisherName} usa questi dati per capire l’uso dell’app, l’attività degli account e le scelte di upgrade, e decidere cosa migliorare in TablePro. Puoi interrompere la condivisione in **Preferences > General > Privacy > Share Usage Data**. + +Quando la condivisione è attiva, l’app invia un evento: + +- una volta per giorno locale mentre è in esecuzione, con i tipi di database e il numero di connessioni aperte; +- per il primo tentativo di connessione, la prima connessione riuscita e la prima query riuscita nell’editor, ciascuno una volta per installazione, con il tipo di database. Un traguardo raggiunto con la condivisione disattivata non viene inviato in seguito; +- ogni volta che accedi, con il metodo di accesso, e ogni volta che scegli di uscire dall’account; +- a ogni clic su Upgrade o Buy a License, con il punto dell’app in cui hai fatto clic; +- ogni volta che compare l’invito ad acquistare una licenza e quando rispondi con Buy a License. Il numero di giorni di utilizzo dell’app resta sul tuo computer. + +Prima dell’accesso, gli eventi contengono un ID di installazione casuale. Dopo l’accesso contengono invece l’ID dell’account, collegando a esso l’attività precedente. Il suo profilo PostHog conserva le versioni dell’app e del sistema operativo, l’architettura del processore e la lingua dell’interfaccia. Uscire dall’account genera un nuovo ID casuale. + +Gli eventi vanno direttamente a PostHog, nostro responsabile del trattamento per l’analisi del prodotto, su `eu.i.posthog.com`, nel suo cloud UE. Ogni evento contiene anche il nome e la versione del sistema operativo, la versione della libreria di analisi, un ID evento e l’ora. PostHog vede il tuo indirizzo IP e ne ricava una posizione approssimativa, come paese e città. Vedi [Trasferimenti internazionali](#transfers). + +Questi eventi non contengono mai nomi host dei database, credenziali, testo SQL o contenuti delle righe. L’evento della prima query registra che è riuscita e il tipo di database, non la query stessa. + +Disattivare la condivisione revoca il consenso e interrompe gli invii futuri, inclusi gli eventi in attesa. Una richiesta già in transito può ancora arrivare. Non cancella i dati già ricevuti. [Non abbiamo fissato un limite di conservazione per questi eventi](#retention). Per accedervi o cancellarli, vedi [I tuoi diritti](#rights) o scrivi a [{email}](mailto:{email}). + ## TablePro per iPhone e iPad {#ios-app} **Non viene inviato nulla a TablePro finché non attivi Share Usage Data**, al primo avvio dell'app oppure in seguito in **Settings > Privacy**. Se lo fai, l'app invia un rapporto una volta al giorno allo stesso server delle versioni dell'app per Mac precedenti agli account TablePro e il nostro server lo inoltra a PostHog nello stesso modo, senza il relativo indirizzo IP. Il rapporto contiene un hash SHA-256 dell'identificatore assegnato da Apple all'app sul dispositivo, la piattaforma, le versioni dell'app e di iOS, l'architettura del processore, la lingua dell'app, i nomi dei tipi di database delle connessioni aperte, il numero di connessioni aperte, e la data e l'ora del primo tentativo di connessione, della prima connessione riuscita e della prima query. Non contiene impostazioni degli aggiornamenti e indica sempre che nessuna licenza è attivata, perché l'app non ha né le une né l'altra. @@ -207,7 +227,7 @@ Per i lettori dello Spazio economico europeo e del Regno Unito, le basi giuridic - **Contratto** (Art. 6(1)(b)): vendita e fornitura della licenza, il tuo account con i suoi metodi di accesso e dispositivi, verifiche della licenza, portale account e Team Library. - **Legittimo interesse** (Art. 6(1)(f)): dati di utilizzo dell'app per Mac e relativa analisi in PostHog, eventi su accessi, acquisti, dispositivi e team che il nostro server invia a PostHog, registro di audit dell'account, sicurezza e prevenzione degli abusi, compreso Cloudflare Turnstile nel modulo della newsletter, registri del server, Cloudflare Web Analytics, record di attribuzione degli acquisti, ricerca del paese per la lingua e lo sconto regionale, e chat dal vivo su ogni pagina. -- **Consenso** (Art. 6(1)(a)): cookie di Google Analytics, rapporto sull'utilizzo dell'app per iPhone e iPad, newsletter e conversazioni che avvii nella chat dal vivo. +- **Consenso** (Art. 6(1)(a)): dati di utilizzo dell’app per Linux, cookie di Google Analytics, rapporto sull'utilizzo dell'app per iPhone e iPad, newsletter e conversazioni che avvii nella chat dal vivo. - **Obbligo legale** (Art. 6(1)(c)): registri fiscali e contabili e risposte a richieste legittime. ## Chi riceve i dati {#sharing} diff --git a/resources/data/legal/ja/privacy.md b/resources/data/legal/ja/privacy.md index b60ad8f9..e86aa684 100644 --- a/resources/data/legal/ja/privacy.md +++ b/resources/data/legal/ja/privacy.md @@ -1,14 +1,14 @@ --- title: プライバシーポリシー description: TablePro のアプリ、ウェブサイト、アカウントポータルが収集する情報、送信先、保存期間、変更・削除方法を説明します。 -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -このポリシーは、Mac 版 TablePro、iPhone・iPad 版 TablePro、tablepro.app のウェブサイト、docs.tablepro.app のドキュメント、account.tablepro.app のアカウントポータルに適用されます。それぞれが現在実際に送信・保存している情報を説明します。両アプリは AGPLv3 のオープンソースで、以下のデータを送信するコードは [TablePro のリポジトリ]({github})で確認できます。 +このポリシーは、Mac 版 TablePro、Linux 版 TablePro、iPhone・iPad 版 TablePro、tablepro.app のウェブサイト、docs.tablepro.app のドキュメント、account.tablepro.app のアカウントポータルに適用されます。それぞれが現在実際に送信・保存している情報を説明します。各アプリは AGPLv3 のオープンソースで、以下のデータを送信するコードは [TablePro のリポジトリ]({github})で確認できます。 ## 概要 {#summary} -- Mac アプリは利用状況データを送信します。初期設定でオンですが、オフにできます。iPhone・iPad アプリは、お客様がオンにした場合のみ利用状況レポートを送信します。 +- Mac アプリは利用状況データを送信します。初期設定でオンですが、オフにできます。iPhone・iPad アプリは、お客様がオンにした場合のみ利用状況レポートを送信します。 [Linux アプリ](#linux-usage-data)は、Share を選んだ後にのみ使用状況データを送信します。 - TablePro アカウントにサインインするかライセンスキーを有効化すると、Mac アプリは Mac を名前とともに運営者のサーバーに登録し、定期的にプランを確認します。 - 実行したクエリ、結果、パスワードは TablePro に送信されません。例外は、お客様が Team Library に公開する接続設定(パスワードは含まれません)と保存済みクエリです。 - AI リクエストは Mac アプリから設定した AI プロバイダーへ直接送られ、運営者には送られません。 @@ -106,6 +106,26 @@ Mac アプリは、お客様が設定した場合にのみ次のサービスへ パスワードは macOS キーチェーンに保存されます。接続一覧、クエリ履歴、Query Insights、Data Rewind のスナップショット、設定、開いているタブは Mac に保存されます。SSH キーはディスク上の場所を参照し、コピーはしません。TablePro アカウントに対応する前のバージョンには、クラッシュレポーターや他社のアクセス解析ライブラリは含まれていません。TablePro アカウントに対応したバージョン以降は、上記の利用状況データを送る PostHog のライブラリを含みます。このライブラリには PostHog のクラッシュレポーターが含まれますが、アプリはオフのままにしているため、クラッシュレポートは送信されません。ライブラリは、ランダムな ID、設定、まだ送っていないイベントを `~/Library/Application Support/com.TablePro` 内のファイルに保存します。 +## Linux の使用状況データ {#linux-usage-data} + +**Share を選ぶまで、データは送信されません。** 同意をいただいた場合、{publisherName} はこのデータからアプリの使い方、アカウントの利用状況、アップグレードの選択を把握し、TablePro の改善点を決めます。共有は **Preferences > General > Privacy > Share Usage Data** で停止できます。 + +共有が有効な間、アプリは次のイベントを送信します。 + +- アプリの実行中、現地の日付で 1 日に 1 回、データベースの種類と開いている接続数。 +- 初めての接続試行、初めて成功した接続、クエリエディターで初めて成功したクエリを、インストールごとにそれぞれ 1 回、データベースの種類とともに送信します。共有が無効な間に達成した項目は、後から送信されません。 +- サインインのたびにその方法を送信し、自分でサインアウトを選ぶたびにその操作を送信します。 +- Upgrade または Buy a License をクリックするたびに、クリックした場所。 +- ライセンス購入の案内が表示されるたびと、Buy a License で応答したとき。アプリを使った日数はコンピューター内に保存されます。 + +サインイン前のイベントには、インストールごとのランダムな ID が付きます。サインイン後はアカウント ID が付き、それまでの利用状況もアカウントに関連付けられます。その PostHog プロフィールには、アプリと OS のバージョン、プロセッサーのアーキテクチャ、画面の言語が保存されます。サインアウトすると、新しいランダムな ID が作られます。 + +イベントは、製品分析のデータ処理を委託する PostHog の EU クラウドの `eu.i.posthog.com` に直接送信されます。各イベントには OS の名前とバージョン、分析ライブラリのバージョン、イベント ID、時刻も含まれます。PostHog は IP アドレスを受け取り、国や都市などのおおよその位置を推定します。[国際的なデータ移転](#transfers)をご覧ください。 + +これらのイベントには、データベースのホスト名、認証情報、SQL テキスト、行の内容は一切含まれません。初回クエリのイベントは、成功したこととデータベースの種類を記録し、クエリ自体は記録しません。 + +共有を無効にすると同意が撤回され、待機中のイベントも含め、その後の送信が停止します。すでに送信中のリクエストは届く場合があります。受信済みのデータは削除されません。これらのイベントには[保存期限を設けていません](#retention)。開示や削除については[お客様の権利](#rights)を確認するか、[{email}](mailto:{email}) にご連絡ください。 + ## iPhone・iPad 版 TablePro {#ios-app} 初回起動時または **Settings > Privacy** で、**Share Usage Data をオンにしない限り、TablePro へは何も送信されません**。オンにすると、TablePro アカウントに対応する前の Mac アプリと同じサーバーへ 1 日 1 回レポートを送ります。サーバーは同じ方法でレポートを PostHog に転送し、IP アドレスは送りません。レポートには、Apple がデバイス上のアプリに付与する識別子の SHA-256 ハッシュ、プラットフォーム、アプリと iOS のバージョン、プロセッサアーキテクチャ、アプリの言語、開いている接続のデータベースの種類の名前、開いている接続の数、初めて接続を試みた日時、初めて接続に成功した日時、初めてクエリを実行した日時が含まれます。アップデート設定は含まれず、ライセンスは常に「有効化されていない」と報告されます。アプリにはどちらも存在しないためです。 @@ -207,7 +227,7 @@ account.tablepro.app の[アカウントポータル]({account})では、TablePr - **契約**(第 6 条第 1 項(b)):ライセンスの販売・提供、サインイン方法とデバイスを含むアカウント、ライセンス確認、アカウントポータル、Team Library。 - **正当な利益**(第 6 条第 1 項(f)):Mac アプリの利用状況データと PostHog での分析、運営者のサーバーが PostHog に送るサインイン・購入・デバイス・チームに関するイベント、アカウントの監査ログ、ニュースレターのフォームでの Cloudflare Turnstile を含むセキュリティと不正利用防止、サーバーログ、Cloudflare Web Analytics、購入の流入元記録、言語と地域割引のための国の照会、すべてのページのチャット。 -- **同意**(第 6 条第 1 項(a)):Google Analytics の Cookie、iPhone・iPad アプリの利用状況レポート、ニュースレター、お客様が開始するチャットの会話。 +- **同意**(第 6 条第 1 項(a)):Linux アプリの使用状況データ、Google Analytics の Cookie、iPhone・iPad アプリの利用状況レポート、ニュースレター、お客様が開始するチャットの会話。 - **法的義務**(第 6 条第 1 項(c)):税務・会計記録、適法な要請への回答。 ## データの受領者 {#sharing} diff --git a/resources/data/legal/ko/privacy.md b/resources/data/legal/ko/privacy.md index 866632f1..a969fded 100644 --- a/resources/data/legal/ko/privacy.md +++ b/resources/data/legal/ko/privacy.md @@ -1,14 +1,14 @@ --- title: 개인정보 처리방침 description: TablePro 앱, 웹사이트 및 계정 포털이 수집하는 정보, 전송 대상, 보관 기간과 변경 또는 삭제 방법을 설명합니다. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -이 방침은 Mac용 TablePro, iPhone 및 iPad용 TablePro, tablepro.app 웹사이트, docs.tablepro.app 문서 및 account.tablepro.app 계정 포털에 적용됩니다. 각 제품이 현재 실제로 전송하고 저장하는 정보를 설명합니다. 두 앱은 모두 AGPLv3로 공개된 오픈 소스이므로 아래 데이터를 전송하는 코드를 [TablePro 저장소]({github})에서 확인할 수 있습니다. +이 방침은 Mac용 TablePro, Linux용 TablePro, iPhone 및 iPad용 TablePro, tablepro.app 웹사이트, docs.tablepro.app 문서 및 account.tablepro.app 계정 포털에 적용됩니다. 각 제품이 현재 실제로 전송하고 저장하는 정보를 설명합니다. 앱은 모두 AGPLv3로 공개된 오픈 소스이므로 아래 데이터를 전송하는 코드를 [TablePro 저장소]({github})에서 확인할 수 있습니다. ## 요약 {#summary} -- Mac 앱은 사용 데이터를 보냅니다. 기본적으로 켜져 있으며 끌 수 있습니다. iPhone 및 iPad 앱은 사용자가 켜는 경우에만 사용 보고서를 보냅니다. +- Mac 앱은 사용 데이터를 보냅니다. 기본적으로 켜져 있으며 끌 수 있습니다. iPhone 및 iPad 앱은 사용자가 켜는 경우에만 사용 보고서를 보냅니다. [Linux 앱](#linux-usage-data)은 Share를 선택한 후에만 사용 데이터를 전송합니다. - TablePro 계정에 로그인하거나 라이선스 키를 활성화하면 Mac 앱은 Mac을 이름과 함께 운영자의 서버에 등록하고 정기적으로 플랜을 확인합니다. - 실행한 쿼리, 결과 및 비밀번호는 TablePro에 전송되지 않습니다. 예외는 Team Library에 직접 게시하는 연결 설정(비밀번호는 제외)과 저장된 쿼리입니다. - AI 요청은 Mac 앱에서 설정한 AI 제공업체로 직접 전송되며 운영자를 거치지 않습니다. @@ -106,6 +106,26 @@ Mac 앱은 아래 서비스를 설정한 경우에만 데이터를 직접 전송 비밀번호는 macOS 키체인에 보관됩니다. 연결 목록, 쿼리 기록, Query Insights, Data Rewind 스냅샷, 설정 및 열린 탭은 Mac에 저장됩니다. 앱은 디스크의 SSH 키 위치를 참조하며 복사하지 않습니다. TablePro 계정을 지원하기 전 버전에는 충돌 보고 도구나 타사 분석 라이브러리가 없습니다. TablePro 계정을 지원하는 버전부터는 위에서 설명한 사용 데이터를 보내는 PostHog 라이브러리가 포함됩니다. 이 라이브러리에는 PostHog의 충돌 보고 도구가 들어 있지만 앱이 꺼 둔 채로 두므로 충돌 보고서는 전송되지 않습니다. 라이브러리는 무작위 ID, 설정, 아직 보내지 않은 이벤트를 `~/Library/Application Support/com.TablePro` 아래 파일에 보관합니다. +## Linux 사용 데이터 {#linux-usage-data} + +**Share를 선택하기 전에는 아무 데이터도 전송하지 않습니다.** 동의하시면 {publisherName}은 이 데이터를 통해 앱 사용, 계정 활동, 업그레이드 선택을 파악하고 TablePro의 개선 사항을 결정합니다. **Preferences > General > Privacy > Share Usage Data**에서 공유를 중단할 수 있습니다. + +공유가 켜져 있으면 앱은 다음 이벤트를 전송합니다. + +- 앱 실행 중 현지 날짜 기준 하루 한 번, 데이터베이스 유형과 열린 연결 수; +- 설치마다 첫 연결 시도, 첫 연결 성공, 쿼리 편집기에서의 첫 쿼리 성공을 각각 한 번씩 데이터베이스 유형과 함께 전송합니다. 공유가 꺼진 동안 달성한 항목은 나중에도 전송하지 않습니다; +- 로그인할 때마다 로그인 방법을 전송하고, 직접 로그아웃을 선택할 때마다 로그아웃 이벤트를 전송합니다; +- Upgrade 또는 Buy a License를 클릭할 때마다 클릭한 위치; +- 라이선스 구매 안내가 표시될 때마다, 그리고 Buy a License로 응답할 때. 앱 사용 일수는 컴퓨터에만 저장됩니다. + +로그인 전에는 이벤트에 무작위 설치 ID가 포함됩니다. 로그인 후에는 계정 ID를 사용하여 이전 활동을 해당 계정에 연결합니다. 계정의 PostHog 프로필에는 앱과 운영체제 버전, 프로세서 아키텍처, 인터페이스 언어가 저장됩니다. 로그아웃하면 새 무작위 ID가 만들어집니다. + +이벤트는 제품 분석을 맡긴 데이터 처리업체인 PostHog의 EU 클라우드 `eu.i.posthog.com`으로 직접 전송됩니다. 각 이벤트에는 운영체제 이름과 버전, 분석 라이브러리 버전, 이벤트 ID와 시간도 포함됩니다. PostHog는 IP 주소를 보고 국가와 도시 같은 대략적인 위치를 추정합니다. [국외 이전](#transfers)을 참고하세요. + +이 이벤트에는 데이터베이스 호스트 이름, 인증 정보, SQL 텍스트 또는 행 내용이 절대 포함되지 않습니다. 첫 쿼리 이벤트는 쿼리가 성공했다는 사실과 데이터베이스 유형만 기록하며, 쿼리 자체는 기록하지 않습니다. + +공유를 끄면 동의가 철회되며 대기 중인 이벤트를 포함한 이후 전송이 중단됩니다. 이미 전송 중인 요청은 도착할 수 있습니다. 이미 받은 데이터는 삭제되지 않습니다. 이 이벤트의 [보관 기한은 정하지 않았습니다](#retention). 열람이나 삭제는 [귀하의 권리](#rights)를 참고하거나 [{email}](mailto:{email})로 문의하세요. + ## iPhone 및 iPad용 TablePro {#ios-app} 앱을 처음 시작할 때 또는 이후 **설정 > 개인정보 보호**(Settings > Privacy)에서 **사용 데이터 공유(Share Usage Data)를 켜지 않으면 아무것도 TablePro에 전송되지 않습니다**. 켜면 TablePro 계정을 지원하기 전 버전의 Mac 앱과 같은 서버에 하루에 한 번 보고서를 보내며, 서버는 같은 방식으로 보고서를 IP 주소 없이 PostHog에 전달합니다. 보고서에는 Apple이 기기의 앱에 부여한 식별자의 SHA-256 해시, 플랫폼, 앱 및 iOS 버전, 프로세서 아키텍처, 앱 언어, 열려 있는 연결의 데이터베이스 유형 이름, 열려 있는 연결 수, 그리고 처음 연결을 시도한 날짜와 시간, 처음 연결에 성공한 날짜와 시간 및 첫 쿼리를 실행한 날짜와 시간이 포함됩니다. 앱에는 업데이트 설정과 라이선스가 없으므로 업데이트 설정은 포함되지 않으며 라이선스는 항상 활성화되지 않은 것으로 보고됩니다. @@ -207,7 +227,7 @@ account.tablepro.app의 [계정 포털]({account})에서 TablePro 계정의 라 - **계약**(제6조 제1항 (b)): 라이선스 판매 및 제공, 로그인 방법과 기기를 포함한 계정, 라이선스 확인, 계정 포털 및 Team Library. - **정당한 이익**(제6조 제1항 (f)): Mac 앱 사용 데이터와 PostHog에서의 분석, 운영자의 서버가 PostHog에 보내는 로그인·구매·기기·팀 관련 이벤트, 계정 감사 로그, 뉴스레터 양식의 Cloudflare Turnstile을 포함한 보안 및 남용 방지, 서버 로그, Cloudflare Web Analytics, 구매 유입 기록, 언어 및 지역 할인을 위한 국가 조회, 모든 페이지의 실시간 채팅. -- **동의**(제6조 제1항 (a)): Google Analytics 쿠키, iPhone 및 iPad 앱 사용 보고서, 뉴스레터 및 사용자가 시작하는 실시간 채팅 대화. +- **동의**(제6조 제1항 (a)): Linux 앱 사용 데이터, Google Analytics 쿠키, iPhone 및 iPad 앱 사용 보고서, 뉴스레터 및 사용자가 시작하는 실시간 채팅 대화. - **법적 의무**(제6조 제1항 (c)): 세금 및 회계 기록, 적법한 요청에 대한 응답. ## 데이터 수신 대상 {#sharing} diff --git a/resources/data/legal/pt-BR/privacy.md b/resources/data/legal/pt-BR/privacy.md index 55e2702a..697209bb 100644 --- a/resources/data/legal/pt-BR/privacy.md +++ b/resources/data/legal/pt-BR/privacy.md @@ -1,14 +1,14 @@ --- title: Política de privacidade description: O que os apps, site e portal da conta TablePro coletam, para onde os dados vão, por quanto tempo são mantidos e como alterá-los ou excluí-los. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Esta política abrange TablePro para Mac, TablePro para iPhone e iPad, o site tablepro.app, a documentação em docs.tablepro.app e o portal da conta account.tablepro.app. Descreve o que cada um realmente envia e armazena hoje. Os dois apps são de código aberto sob a AGPLv3, portanto você pode ler o código que envia os dados abaixo no [repositório TablePro]({github}). +Esta política abrange TablePro para Mac, TablePro para Linux, TablePro para iPhone e iPad, o site tablepro.app, a documentação em docs.tablepro.app e o portal da conta account.tablepro.app. Descreve o que cada um realmente envia e armazena hoje. Os apps são de código aberto sob a AGPLv3, portanto você pode ler o código que envia os dados abaixo no [repositório TablePro]({github}). ## Resumo {#summary} -- O app para Mac envia dados de uso. Está ativado por padrão e pode ser desativado. O app para iPhone e iPad só envia um relatório de uso se você ativar. +- O app para Mac envia dados de uso. Está ativado por padrão e pode ser desativado. O app para iPhone e iPad só envia um relatório de uso se você ativar. O [app para Linux](#linux-usage-data) só envia dados de uso depois que você escolhe Share. - Se você entrar em uma conta TablePro ou ativar uma chave de licença, o app para Mac registra seu Mac em nosso servidor, com o nome dele, e verifica seu plano com ele regularmente. - Consultas, resultados e senhas não são enviados ao TablePro. A exceção é o que você escolhe publicar na Team Library: configurações de conexão (nunca senhas) e consultas salvas. - Solicitações de IA vão do app para Mac diretamente ao provedor configurado por você, não a nós. @@ -106,6 +106,26 @@ O app para Mac só envia dados a estes serviços quando você os configura, dire As senhas ficam nas Chaves do macOS. Lista de conexões, histórico de consultas, Query Insights, snapshots de Data Rewind, configurações e abas abertas são armazenados no Mac. O app referencia as chaves SSH onde estão no disco e não as copia. As versões anteriores às contas TablePro não contêm relator de falhas nem biblioteca de análise de terceiros. A partir da versão que traz as contas TablePro, o app inclui a biblioteca do PostHog, que envia os dados de uso descritos acima. A biblioteca contém o relator de falhas do PostHog, que o app mantém desativado, então nenhum relatório de falha é enviado. Ela guarda seu ID aleatório, suas configurações e os eventos ainda não enviados em arquivos em `~/Library/Application Support/com.TablePro`. +## Dados de uso no Linux {#linux-usage-data} + +**Nada é enviado até você escolher Share.** Com seu consentimento, {publisherName} usa esses dados para entender o uso do app, a atividade das contas e as escolhas de upgrade, e decidir o que melhorar no TablePro. Você pode parar de compartilhar em **Preferences > General > Privacy > Share Usage Data**. + +Enquanto o compartilhamento está ativo, o app envia um evento: + +- uma vez por dia local enquanto está em execução, com os tipos de bancos de dados e o número de conexões abertas; +- para a primeira tentativa de conexão, a primeira conexão bem-sucedida e a primeira consulta bem-sucedida no editor, cada uma uma vez por instalação, com o tipo de banco de dados. Um marco atingido com o compartilhamento desativado nunca é enviado depois; +- sempre que você entra na conta, com o método de acesso, e sempre que escolhe sair; +- a cada clique em Upgrade ou Buy a License, com o local do clique; +- sempre que o aviso de compra de licença aparece e quando você responde com Buy a License. O número de dias de uso do app fica no seu computador. + +Antes de entrar na conta, os eventos levam um ID aleatório da instalação. Depois, levam o ID da conta, vinculando a atividade anterior a ela. Seu perfil no PostHog guarda as versões do app e do sistema operacional, a arquitetura do processador e o idioma da interface. Sair da conta cria um novo ID aleatório. + +Os eventos vão diretamente ao PostHog, nosso operador de dados para análise do produto, em `eu.i.posthog.com`, na nuvem da UE. Cada evento também leva o nome e a versão do sistema operacional, a versão da biblioteca de análise, um ID de evento e o horário. O PostHog vê seu endereço IP e deduz uma localização aproximada, como país e cidade. Veja [Transferências internacionais](#transfers). + +Esses eventos nunca contêm nomes de host de bancos de dados, credenciais, texto SQL ou conteúdo de linhas. O evento da primeira consulta registra que ela foi concluída e o tipo de banco de dados, não a consulta em si. + +Desativar o compartilhamento retira seu consentimento e interrompe envios futuros, incluindo eventos na fila. Uma solicitação já em trânsito ainda pode chegar. Isso não apaga dados já recebidos. [Não definimos um prazo de retenção para esses eventos](#retention). Para acessar ou apagar seus dados, veja [Seus direitos](#rights) ou escreva para [{email}](mailto:{email}). + ## TablePro para iPhone e iPad {#ios-app} **Nada vai ao TablePro, a menos que você ative Share Usage Data**, na primeira inicialização ou depois em **Settings > Privacy**. Nesse caso, o app envia um relatório diário ao mesmo servidor das versões do app para Mac anteriores às contas TablePro, e nosso servidor o repassa ao PostHog da mesma forma, sem o IP. O relatório contém um hash SHA-256 do identificador atribuído pela Apple ao app no dispositivo, plataforma, versões do app e iOS, arquitetura do processador, idioma, nomes dos tipos de banco das conexões abertas, quantas estão abertas, e a data e a hora da primeira tentativa de conexão, da primeira conexão bem-sucedida e da primeira consulta. Não inclui configurações de atualização e sempre informa que não há licença ativada, pois o app não tem nenhuma das duas coisas. @@ -207,7 +227,7 @@ Para leitores no Espaço Econômico Europeu e Reino Unido, as bases legais sob o - **Contrato** (Art. 6(1)(b)): vender e fornecer licenças, sua conta com seus métodos de acesso e dispositivos, verificações de licença, portal da conta e Team Library. - **Interesse legítimo** (Art. 6(1)(f)): dados de uso do app para Mac e sua análise no PostHog, eventos sobre acessos, compras, dispositivos e equipes que nosso servidor envia ao PostHog, registro de auditoria da conta, segurança e prevenção de abuso, incluindo o Cloudflare Turnstile no formulário da newsletter, logs do servidor, Cloudflare Web Analytics, registro de atribuição de compras, consulta de país para o idioma e o desconto regional, e chat ao vivo em todas as páginas. -- **Consentimento** (Art. 6(1)(a)): cookies Google Analytics, relatório de uso do app para iPhone e iPad, newsletter e conversas iniciadas no chat ao vivo. +- **Consentimento** (Art. 6(1)(a)): dados de uso do app para Linux, cookies Google Analytics, relatório de uso do app para iPhone e iPad, newsletter e conversas iniciadas no chat ao vivo. - **Obrigação legal** (Art. 6(1)(c)): registros fiscais e contábeis e respostas a solicitações legais. ## Quem recebe dados {#sharing} diff --git a/resources/data/legal/vi/privacy.md b/resources/data/legal/vi/privacy.md index 5ddab446..5616e9b7 100644 --- a/resources/data/legal/vi/privacy.md +++ b/resources/data/legal/vi/privacy.md @@ -1,14 +1,14 @@ --- title: Chính sách quyền riêng tư description: Ứng dụng, website và trang tài khoản của TablePro thu thập những gì, gửi đi đâu, lưu trong bao lâu, và cách bạn thay đổi hoặc xóa dữ liệu đó. -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -Chính sách này áp dụng cho TablePro cho Mac, TablePro cho iPhone và iPad, website tablepro.app, trang tài liệu docs.tablepro.app và trang tài khoản account.tablepro.app. Chính sách mô tả đúng những gì từng thành phần đang gửi đi và lưu lại ở thời điểm hiện tại. Cả hai ứng dụng đều là mã nguồn mở theo giấy phép AGPLv3, nên bạn có thể đọc phần mã gửi đi mọi dữ liệu nêu dưới đây trong [kho mã nguồn TablePro]({github}). +Chính sách này áp dụng cho TablePro cho Mac, TablePro cho Linux, TablePro cho iPhone và iPad, website tablepro.app, trang tài liệu docs.tablepro.app và trang tài khoản account.tablepro.app. Chính sách mô tả đúng những gì từng thành phần đang gửi đi và lưu lại ở thời điểm hiện tại. Các ứng dụng đều là mã nguồn mở theo giấy phép AGPLv3, nên bạn có thể đọc phần mã gửi đi mọi dữ liệu nêu dưới đây trong [kho mã nguồn TablePro]({github}). ## Tóm tắt {#summary} -- Ứng dụng cho Mac gửi dữ liệu sử dụng. Tính năng này bật sẵn và bạn có thể tắt. Ứng dụng cho iPhone và iPad chỉ gửi báo cáo sử dụng khi bạn bật nó lên. +- Ứng dụng cho Mac gửi dữ liệu sử dụng. Tính năng này bật sẵn và bạn có thể tắt. Ứng dụng cho iPhone và iPad chỉ gửi báo cáo sử dụng khi bạn bật nó lên. [Ứng dụng Linux](#linux-usage-data) chỉ gửi dữ liệu sử dụng sau khi bạn chọn Share. - Nếu bạn đăng nhập tài khoản TablePro hoặc kích hoạt license key, ứng dụng cho Mac đăng ký máy Mac của bạn với máy chủ của chúng tôi, kèm tên máy, và định kỳ kiểm tra gói của bạn với máy chủ. - Các query bạn chạy, kết quả trả về và mật khẩu của bạn không được gửi cho TablePro. Ngoại lệ duy nhất là những gì bạn chủ động xuất bản lên Team Library: cấu hình connection (không bao giờ gồm mật khẩu) và query đã lưu. - Yêu cầu gửi tới AI đi thẳng từ ứng dụng cho Mac tới nhà cung cấp AI mà bạn thiết lập, không qua chúng tôi. @@ -106,6 +106,26 @@ GitHub nhận địa chỉ IP của bạn qua các yêu cầu này. Tuyên bố Mật khẩu được lưu trong Keychain của macOS. Danh sách connection, lịch sử query, Query Insights, các bản chụp của Data Rewind, cài đặt và các tab đang mở được lưu trên máy Mac của bạn. Ứng dụng chỉ tham chiếu tới SSH key ở đúng vị trí của chúng trên ổ đĩa và không sao chép chúng. Các phiên bản trước khi có tài khoản TablePro không chứa công cụ báo lỗi (crash reporter) nào và không có thư viện phân tích của bên thứ ba. Từ phiên bản có tài khoản TablePro, ứng dụng có thư viện của PostHog, dùng để gửi dữ liệu sử dụng nêu ở trên. Thư viện này có công cụ báo lỗi (crash reporter) của PostHog, nhưng ứng dụng luôn để nó tắt, nên không gửi báo cáo lỗi nào. Thư viện lưu mã ngẫu nhiên, cấu hình và các sự kiện chưa gửi của nó trong các tệp dưới `~/Library/Application Support/com.TablePro`. +## Dữ liệu sử dụng trên Linux {#linux-usage-data} + +**Không có dữ liệu nào được gửi cho đến khi bạn chọn Share.** Khi có sự đồng ý của bạn, {publisherName} dùng dữ liệu này để hiểu cách dùng ứng dụng, hoạt động tài khoản và lựa chọn nâng cấp, rồi quyết định cần cải thiện gì trong TablePro. Bạn có thể ngừng chia sẻ tại **Tùy chỉnh > Tổng quát > Privacy > Share Usage Data** (Preferences > General > Privacy > Share Usage Data). + +Khi bật chia sẻ, ứng dụng gửi một sự kiện: + +- mỗi ngày theo giờ địa phương khi ứng dụng chạy, kèm loại database và số connection đang mở; +- cho lần thử kết nối đầu tiên, lần kết nối thành công đầu tiên và query thành công đầu tiên trong query editor, mỗi mốc một lần cho mỗi bản cài đặt, kèm loại database. Mốc đạt được khi tắt chia sẻ sẽ không được gửi lại sau đó; +- mỗi lần bạn đăng nhập, kèm phương thức đăng nhập, và mỗi lần bạn chọn đăng xuất; +- mỗi lần bạn bấm Upgrade hoặc Buy a License, kèm vị trí bạn bấm; +- mỗi lần lời nhắc mua license xuất hiện và khi bạn trả lời bằng Buy a License. Số ngày bạn dùng ứng dụng chỉ được lưu trên máy tính của bạn. + +Trước khi đăng nhập, sự kiện mang ID ngẫu nhiên của bản cài đặt. Sau khi đăng nhập, chúng mang ID tài khoản, liên kết hoạt động trước đó với tài khoản này. Hồ sơ trên PostHog lưu phiên bản ứng dụng và hệ điều hành, kiến trúc bộ xử lý và ngôn ngữ giao diện. Đăng xuất tạo một ID ngẫu nhiên mới. + +Sự kiện được gửi thẳng đến PostHog, bên xử lý dữ liệu phân tích sản phẩm của chúng tôi, tại `eu.i.posthog.com` trên dịch vụ đám mây EU của họ. Mỗi sự kiện còn mang tên và phiên bản hệ điều hành, phiên bản thư viện phân tích, ID và thời gian sự kiện. PostHog thấy địa chỉ IP của bạn và suy ra vị trí gần đúng, như quốc gia và thành phố. Xem [Chuyển dữ liệu quốc tế](#transfers). + +Các sự kiện này không bao giờ chứa tên host của database, thông tin xác thực, nội dung SQL hay dữ liệu trong các hàng. Sự kiện query đầu tiên ghi nhận query đã thành công và loại database, không ghi nội dung query. + +Tắt chia sẻ là rút lại sự đồng ý và dừng việc gửi tiếp, kể cả các sự kiện đang chờ. Yêu cầu đang trên đường truyền vẫn có thể đến nơi. Thao tác này không xóa dữ liệu đã nhận: chúng tôi [chưa đặt thời hạn lưu các sự kiện này](#retention). Để truy cập hoặc xóa dữ liệu, xem [Quyền của bạn](#rights) hoặc gửi email đến [{email}](mailto:{email}). + ## TablePro cho iPhone và iPad {#ios-app} **Không có gì được gửi tới TablePro trừ khi bạn bật Chia sẻ dữ liệu sử dụng** (Share Usage Data), khi ứng dụng khởi động lần đầu hoặc sau đó trong **Cài đặt > Quyền riêng tư** (Settings > Privacy). Nếu bạn bật, ứng dụng gửi một báo cáo mỗi ngày tới cùng máy chủ với các phiên bản ứng dụng cho Mac trước khi có tài khoản TablePro, và máy chủ của chúng tôi chuyển báo cáo sang PostHog theo cùng cách, không kèm địa chỉ IP. Báo cáo gồm giá trị băm SHA-256 của mã định danh mà Apple cấp cho ứng dụng trên thiết bị của bạn, nền tảng, phiên bản ứng dụng và iOS, kiến trúc bộ xử lý, ngôn ngữ của ứng dụng, tên các loại cơ sở dữ liệu của những connection bạn đang mở, số connection đang mở, và ngày giờ bạn thử kết nối lần đầu, kết nối thành công lần đầu và chạy query đầu tiên. Báo cáo không có cài đặt cập nhật và luôn ghi là chưa kích hoạt license nào, vì ứng dụng không có cả hai. @@ -207,7 +227,7 @@ Với người đọc ở Khu vực Kinh tế Châu Âu (EEA) và Vương quốc - **Hợp đồng** (Điều 6(1)(b)): bán và cung cấp license, tài khoản của bạn cùng các cách đăng nhập và thiết bị, kiểm tra license, trang tài khoản và Team Library. - **Lợi ích hợp pháp** (Điều 6(1)(f)): dữ liệu sử dụng của ứng dụng cho Mac và việc phân tích dữ liệu đó trong PostHog, các sự kiện về đăng nhập, mua hàng, thiết bị và nhóm mà máy chủ của chúng tôi gửi tới PostHog, nhật ký kiểm tra của tài khoản, bảo mật và chống lạm dụng, gồm cả Cloudflare Turnstile trên form đăng ký bản tin, nhật ký máy chủ, Cloudflare Web Analytics, bản ghi nguồn truy cập khi mua hàng, việc tra quốc gia để gợi ý ngôn ngữ và giảm giá theo khu vực, và khung chat trực tuyến trên mọi trang. -- **Sự đồng ý** (Điều 6(1)(a)): cookie của Google Analytics, báo cáo sử dụng của ứng dụng cho iPhone và iPad, bản tin và các cuộc chat bạn bắt đầu trong chat trực tuyến. +- **Sự đồng ý** (Điều 6(1)(a)): dữ liệu sử dụng của ứng dụng Linux, cookie của Google Analytics, báo cáo sử dụng của ứng dụng cho iPhone và iPad, bản tin và các cuộc chat bạn bắt đầu trong chat trực tuyến. - **Nghĩa vụ pháp lý** (Điều 6(1)(c)): hồ sơ thuế và kế toán, và việc trả lời các yêu cầu hợp pháp. ## Bên nhận dữ liệu {#sharing} diff --git a/resources/data/legal/zh-Hans/privacy.md b/resources/data/legal/zh-Hans/privacy.md index 5e0c3fae..114fd37e 100644 --- a/resources/data/legal/zh-Hans/privacy.md +++ b/resources/data/legal/zh-Hans/privacy.md @@ -1,14 +1,14 @@ --- title: 隐私政策 description: TablePro 应用、网站和账户门户收集什么信息、发送到哪里、保存多久,以及如何更改或删除。 -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -本政策涵盖 Mac 版 TablePro、iPhone 和 iPad 版 TablePro、位于 tablepro.app 的网站、位于 docs.tablepro.app 的文档,以及位于 account.tablepro.app 的账户门户。它描述各产品目前实际发送和存储的信息。两款应用均采用 AGPLv3 开源,您可在 [TablePro 仓库]({github})中查看发送下列数据的代码。 +本政策涵盖 Mac 版 TablePro、Linux 版 TablePro、iPhone 和 iPad 版 TablePro、位于 tablepro.app 的网站、位于 docs.tablepro.app 的文档,以及位于 account.tablepro.app 的账户门户。它描述各产品目前实际发送和存储的信息。这些应用均采用 AGPLv3 开源,您可在 [TablePro 仓库]({github})中查看发送下列数据的代码。 ## 概要 {#summary} -- Mac 应用会发送使用数据。该功能默认开启,可以关闭。iPhone 和 iPad 应用仅在您开启后发送使用情况报告。 +- Mac 应用会发送使用数据。该功能默认开启,可以关闭。iPhone 和 iPad 应用仅在您开启后发送使用情况报告。 [Linux 应用](#linux-usage-data)仅在您选择 Share 后发送使用数据。 - 登录 TablePro 账户或激活许可证密钥后,Mac 应用会将您的 Mac 连同名称登记到我们的服务器,并定期向服务器核对您的方案。 - 您运行的查询、结果和密码不会发送给 TablePro。例外是您自行选择发布到 Team Library 的连接设置(从不包含密码)和已保存查询。 - AI 请求从 Mac 应用直接发送至您设置的 AI 提供商,不经过我们。 @@ -106,6 +106,26 @@ GitHub 会随这些请求收到您的 IP 地址,这些请求适用 GitHub 自 密码保存在 macOS 钥匙串中。连接列表、查询历史、Query Insights、Data Rewind 快照、设置和打开的选项卡存储在 Mac 上。应用引用磁盘上的 SSH 密钥,不会复制它们。支持 TablePro 账户之前的版本不包含崩溃报告工具或第三方分析库。从支持 TablePro 账户的版本起,应用包含 PostHog 的库,用于发送上文所述的使用数据。该库包含 PostHog 的崩溃报告工具,但应用将其保持关闭,因此不会发送崩溃报告。该库将其随机 ID、配置和尚未发送的事件保存在 `~/Library/Application Support/com.TablePro` 下的文件中。 +## Linux 使用数据 {#linux-usage-data} + +**在您选择 Share 之前,不会发送任何数据。** 经您同意,{publisherName} 使用这些数据了解应用使用情况、账户活动和升级选择,以决定如何改进 TablePro。您可以在 **Preferences > General > Privacy > Share Usage Data** 中停止共享。 + +开启共享时,应用会发送以下事件: + +- 应用运行期间,每个本地日发送一次数据库类型和已打开的连接数; +- 每次安装后,首次连接尝试、首次成功连接和在查询编辑器中首次成功执行查询时各发送一次,并附带数据库类型。关闭共享时达到的里程碑不会在之后补发; +- 每次登录时发送登录方式,每次主动选择退出登录时发送退出事件; +- 每次点击 Upgrade 或 Buy a License 时,发送点击位置; +- 每次显示购买许可证提示,以及您通过 Buy a License 回应时。应用使用天数只保存在您的计算机上。 + +登录前,事件携带随机安装 ID。登录后改用账户 ID,将之前的活动关联到该账户。其 PostHog 个人资料保存应用和操作系统版本、处理器架构及界面语言。退出登录会生成新的随机 ID。 + +事件直接发送到 PostHog 欧盟云的 `eu.i.posthog.com`。PostHog 是我们用于产品分析的数据处理者。每个事件还携带操作系统名称和版本、分析库版本、事件 ID 及时间。PostHog 会看到您的 IP 地址,并据此推算国家和城市等大致位置。请参阅[国际数据传输](#transfers)。 + +这些事件绝不包含数据库主机名、凭据、SQL 文本或行内容。首次查询事件只记录查询成功及数据库类型,不记录查询本身。 + +关闭共享即撤回同意,并停止后续发送,包括排队中的事件。已在传输中的请求仍可能送达。这不会删除已经收到的数据:我们[尚未为这些事件设定保留期限](#retention)。如需访问或删除数据,请参阅[您的权利](#rights),或发送邮件至 [{email}](mailto:{email})。 + ## iPhone 和 iPad 版 TablePro {#ios-app} **除非您开启共享使用数据(Share Usage Data),否则不会向 TablePro 发送任何信息**。您可在首次启动时或之后的**设置 > 隐私**(Settings > Privacy)中开启。开启后,应用每天向与支持 TablePro 账户之前的 Mac 应用版本相同的服务器发送一次报告,服务器以相同方式将报告转发给 PostHog,不附带其 IP 地址。报告包含 Apple 为设备上的应用分配的标识符的 SHA-256 哈希值、平台、应用和 iOS 版本、处理器架构、应用语言、已打开连接的数据库类型名称、已打开的连接数量,以及首次尝试连接、首次成功连接和首次运行查询的日期和时间。不包含更新设置,并始终报告未激活许可证,因为应用没有这两项内容。 @@ -207,7 +227,7 @@ Handoff 通过 Apple 在您的设备之间传递当前连接的 ID 和打开的 - **合同**(第 6 条第 1 款 (b)):许可证销售和提供、您的账户及其登录方式和设备、许可证验证、账户门户和 Team Library。 - **合法利益**(第 6 条第 1 款 (f)):Mac 应用使用数据及其在 PostHog 中的分析、我们的服务器发送给 PostHog 的关于登录、购买、设备和团队的事件、账户审计日志、安全和滥用防范(包括邮件订阅表单上的 Cloudflare Turnstile)、服务器日志、Cloudflare Web Analytics、购买归因记录、为语言与地区折扣进行的国家查询,以及每个页面的在线聊天。 -- **同意**(第 6 条第 1 款 (a)):Google Analytics Cookie、iPhone 和 iPad 应用使用报告、邮件订阅和您主动发起的在线聊天。 +- **同意**(第 6 条第 1 款 (a)):Linux 应用使用数据、Google Analytics Cookie、iPhone 和 iPad 应用使用报告、邮件订阅和您主动发起的在线聊天。 - **法律义务**(第 6 条第 1 款 (c)):税务与会计记录,以及对合法请求的回应。 ## 数据接收方 {#sharing} diff --git a/resources/data/legal/zh-Hant/privacy.md b/resources/data/legal/zh-Hant/privacy.md index 9dea90ff..070d9f3a 100644 --- a/resources/data/legal/zh-Hant/privacy.md +++ b/resources/data/legal/zh-Hant/privacy.md @@ -1,14 +1,14 @@ --- title: 隱私權政策 description: TablePro App、網站與帳戶入口網站收集哪些資訊、傳送至何處、保存多久,以及如何變更或刪除。 -updatedAt: "2026-11-04" +updatedAt: "2026-11-05" --- -本政策涵蓋 Mac 版 TablePro、iPhone 與 iPad 版 TablePro、位於 tablepro.app 的網站、位於 docs.tablepro.app 的文件,以及位於 account.tablepro.app 的帳戶入口網站。它描述各產品目前實際傳送和儲存的資訊。兩款 App 均採用 AGPLv3 開放原始碼,您可在 [TablePro 儲存庫]({github})中查看傳送下列資料的程式碼。 +本政策涵蓋 Mac 版 TablePro、Linux 版 TablePro、iPhone 與 iPad 版 TablePro、位於 tablepro.app 的網站、位於 docs.tablepro.app 的文件,以及位於 account.tablepro.app 的帳戶入口網站。它描述各產品目前實際傳送和儲存的資訊。這些 App 均採用 AGPLv3 開放原始碼,您可在 [TablePro 儲存庫]({github})中查看傳送下列資料的程式碼。 ## 概要 {#summary} -- Mac App 會傳送使用資料。此功能預設開啟,可以關閉。iPhone 與 iPad App 僅在您開啟後傳送使用情況報告。 +- Mac App 會傳送使用資料。此功能預設開啟,可以關閉。iPhone 與 iPad App 僅在您開啟後傳送使用情況報告。 [Linux App](#linux-usage-data)僅在您選擇 Share 後傳送使用資料。 - 登入 TablePro 帳戶或啟用授權金鑰後,Mac App 會將您的 Mac 連同名稱登記到我們的伺服器,並定期向伺服器核對您的方案。 - 您執行的查詢、結果與密碼不會傳送給 TablePro。例外是您自行選擇發佈至 Team Library 的連線設定(從不包含密碼)與已儲存查詢。 - AI 請求從 Mac App 直接傳送至您設定的 AI 供應商,不經過我們。 @@ -106,6 +106,26 @@ GitHub 會隨這些請求收到您的 IP 位址,這些請求適用 GitHub 自 密碼保存在 macOS 鑰匙圈中。連線清單、查詢歷史、Query Insights、Data Rewind 快照、設定與開啟的分頁儲存在 Mac 上。App 參照磁碟上的 SSH 金鑰,不會複製它們。支援 TablePro 帳戶之前的版本不包含當機報告工具或第三方分析程式庫。從支援 TablePro 帳戶的版本起,App 包含 PostHog 的程式庫,用於傳送上文所述的使用資料。該程式庫包含 PostHog 的當機報告工具,但 App 讓它保持關閉,因此不會傳送當機報告。程式庫將其隨機 ID、設定與尚未傳送的事件儲存在 `~/Library/Application Support/com.TablePro` 下的檔案中。 +## Linux 使用資料 {#linux-usage-data} + +**在您選擇 Share 之前,不會傳送任何資料。** 經您同意,{publisherName} 使用這些資料了解 App 使用情況、帳戶活動和升級選擇,以決定如何改善 TablePro。您可以在 **Preferences > General > Privacy > Share Usage Data** 中停止分享。 + +開啟分享時,App 會傳送以下事件: + +- App 執行期間,每個本地日傳送一次資料庫類型和已開啟的連線數; +- 每次安裝後,首次連線嘗試、首次成功連線和在查詢編輯器中首次成功執行查詢時各傳送一次,並附上資料庫類型。關閉分享時達到的里程碑不會在之後補送; +- 每次登入時傳送登入方式,每次主動選擇登出時傳送登出事件; +- 每次點擊 Upgrade 或 Buy a License 時,傳送點擊位置; +- 每次顯示購買授權提示,以及您透過 Buy a License 回應時。App 使用天數只保存在您的電腦上。 + +登入前,事件帶有隨機安裝 ID。登入後改用帳戶 ID,將之前的活動連結到該帳戶。其 PostHog 個人資料保存 App 和作業系統版本、處理器架構及介面語言。登出會產生新的隨機 ID。 + +事件直接傳送到 PostHog 歐盟雲端的 `eu.i.posthog.com`。PostHog 是我們用於產品分析的資料處理者。每個事件還帶有作業系統名稱和版本、分析程式庫版本、事件 ID 及時間。PostHog 會看到您的 IP 位址,並據此推算國家和城市等大致位置。請參閱[國際資料傳輸](#transfers)。 + +這些事件絕不包含資料庫主機名稱、憑證、SQL 文字或資料列內容。首次查詢事件只記錄查詢成功及資料庫類型,不記錄查詢本身。 + +關閉分享即撤回同意,並停止後續傳送,包括佇列中的事件。已在傳輸中的請求仍可能送達。這不會刪除已經收到的資料:我們[尚未為這些事件設定保留期限](#retention)。如需存取或刪除資料,請參閱[您的權利](#rights),或寄信至 [{email}](mailto:{email})。 + ## iPhone 與 iPad 版 TablePro {#ios-app} **除非您開啟分享使用資料(Share Usage Data),否則不會向 TablePro 傳送任何資訊**。您可在首次啟動時或之後的**設定 > 隱私權**(Settings > Privacy)中開啟。開啟後,App 每天向與支援 TablePro 帳戶之前的 Mac App 版本相同的伺服器傳送一次報告,伺服器以相同方式將報告轉送給 PostHog,不附帶其 IP 位址。報告包含 Apple 為裝置上的 App 分配的識別碼的 SHA-256 雜湊值、平台、App 和 iOS 版本、處理器架構、App 語言、已開啟連線的資料庫類型名稱、已開啟的連線數量,以及首次嘗試連線、首次成功連線與首次執行查詢的日期和時間。不包含更新設定,並一律回報未啟用授權,因為 App 沒有這兩項內容。 @@ -207,7 +227,7 @@ Mac 上的 iCloud Sync 屬於 Pro 或 Team 授權功能,在 iPhone 與 iPad - **契約**(第 6 條第 1 款 (b)):授權銷售和提供、您的帳戶及其登入方式和裝置、授權驗證、帳戶入口網站和 Team Library。 - **正當利益**(第 6 條第 1 款 (f)):Mac App 使用資料及其在 PostHog 中的分析、我們的伺服器傳送給 PostHog 的關於登入、購買、裝置和團隊的事件、帳戶稽核日誌、安全和濫用防範(包括電子報表單上的 Cloudflare Turnstile)、伺服器日誌、Cloudflare Web Analytics、購買歸因紀錄、為語言與地區折扣進行的國家查詢,以及每個網頁的線上聊天。 -- **同意**(第 6 條第 1 款 (a)):Google Analytics Cookie、iPhone 與 iPad App 使用報告、電子報和您主動發起的線上聊天。 +- **同意**(第 6 條第 1 款 (a)):Linux App 使用資料、Google Analytics Cookie、iPhone 與 iPad App 使用報告、電子報和您主動發起的線上聊天。 - **法律義務**(第 6 條第 1 款 (c)):稅務與會計紀錄,以及對合法請求的回應。 ## 資料接收方 {#sharing} diff --git a/tests/Feature/Landing/LegalPagesTest.php b/tests/Feature/Landing/LegalPagesTest.php index bd619088..d65b4c09 100644 --- a/tests/Feature/Landing/LegalPagesTest.php +++ b/tests/Feature/Landing/LegalPagesTest.php @@ -144,8 +144,8 @@ function legalShape(string $document, string $locale): array ]); it('formats the update date in each language on the server', function (): void { - get('/privacy')->assertInertia(fn(AssertableInertia $page) => $page->where('document.updatedAtFormatted', 'November 4, 2026')); - get('/vi/privacy')->assertInertia(fn(AssertableInertia $page) => $page->where('document.updatedAtFormatted', '4 tháng 11 năm 2026')); + get('/privacy')->assertInertia(fn(AssertableInertia $page) => $page->where('document.updatedAtFormatted', 'November 5, 2026')); + get('/vi/privacy')->assertInertia(fn(AssertableInertia $page) => $page->where('document.updatedAtFormatted', '5 tháng 11 năm 2026')); }); it('indexes each document in every supported language', function (string $route): void { @@ -190,6 +190,13 @@ function legalShape(string $document, string $locale): array } })->with(legalLocales()); +it('renders the Linux consent link target in every language', function (string $locale): void { + $document = app(LegalDocuments::class)->render('privacy', $locale); + + expect(substr_count($document['html'], '

'))->toBe(1); + expect(array_column($document['toc'], 'id'))->toContain('linux-usage-data'); +})->with(legalLocales()); + it('closes every bold span on the rendered page', function (string $locale): void { // CommonMark leaves ** in the text when the mark sits between punctuation and a letter, as in 。**后. foreach (legalDocumentsIn($locale) as $document) { diff --git a/tests/Feature/Localization/AppLabelsTest.php b/tests/Feature/Localization/AppLabelsTest.php index b3b6c3a5..539d5eca 100644 --- a/tests/Feature/Localization/AppLabelsTest.php +++ b/tests/Feature/Localization/AppLabelsTest.php @@ -110,12 +110,25 @@ function appLabelsLegalBold(string $line): array */ function appLabelsOnLegalLine(string $line, array $known): array { + $bold = array_filter(appLabelsLegalBold($line), fn(string $text): bool => array_key_exists($text, $known)); + // A full path has its own translations; its last label may differ on another platform. + $inline = str_replace(array_map(fn(string $label): string => "**{$label}**", $bold), '', $line); + return [ - ...array_filter(appLabelsLegalBold($line), fn(string $text): bool => array_key_exists($text, $known)), - ...array_filter(APP_LABELS_LEGAL_INLINE, fn(string $label): bool => str_contains($line, $label)), + ...$bold, + ...array_filter(APP_LABELS_LEGAL_INLINE, fn(string $label): bool => str_contains($inline, $label)), ]; } +it('checks a full menu path once and still checks labels outside it', function (): void { + $path = 'Preferences > General > Privacy > Share Usage Data'; + $known = require base_path('tests/Support/app-ui-labels.php'); + + expect(appLabelsOnLegalLine("Open **{$path}**.", $known))->toBe([$path]); + expect(appLabelsOnLegalLine("Open **{$path}** or enable Share Usage Data.", $known)) + ->toBe([$path, 'Share Usage Data']); +}); + it('knows the app’s wording for every label the English copy names', function (): void { $known = require base_path('tests/Support/app-ui-labels.php'); $missing = []; diff --git a/tests/Support/app-ui-labels.php b/tests/Support/app-ui-labels.php index 6aad92c3..0511e708 100644 --- a/tests/Support/app-ui-labels.php +++ b/tests/Support/app-ui-labels.php @@ -2,6 +2,7 @@ // Every label the copy puts in a tag or the legal pages quote, with the app's own wording in the languages the app ships: // French, Korean and Chinese on the Mac, Korean and Chinese on iPhone. From the apps' Localizable.xcstrings. +// Linux paths use linux/po/vi.po; untranslated labels stay in English. // A missing language, or an empty row, means the app shows the label in English there. return [ @@ -73,6 +74,7 @@ 'Open the File Read-Only' => ['fr' => 'Ouvrir le fichier en lecture seule'], 'Password' => ['fr' => 'Mot de passe', 'ko' => '암호', 'zh-Hans' => '密码', 'zh-Hant' => '密碼'], 'Passwords' => ['fr' => 'Mots de passe', 'ko' => '암호', 'zh-Hans' => '密码', 'zh-Hant' => '密碼'], + 'Preferences > General > Privacy > Share Usage Data' => ['vi' => 'Tùy chỉnh > Tổng quát > Privacy > Share Usage Data'], 'Preview' => ['fr' => 'Aperçu', 'ko' => '미리보기', 'zh-Hans' => '预览', 'zh-Hant' => '預覽'], 'Preview SQL' => ['fr' => 'Aperçu SQL', 'ko' => 'SQL 미리보기', 'zh-Hans' => '预览 SQL', 'zh-Hant' => '預覽 SQL'], 'Project ID' => ['fr' => 'ID du projet', 'ko' => '프로젝트 ID', 'zh-Hans' => '项目 ID', 'zh-Hant' => '專案 ID'], From feed8c2c5291b149c20d2d9c2b9c44719fa9e480 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Fri, 6 Nov 2026 20:51:54 +0700 Subject: [PATCH 3/3] fix(pricing): point the Linux answer at the table above, not the Pricing page --- resources/data/content/de/pricing.json | 2 +- resources/data/content/en/pricing.json | 2 +- resources/data/content/es/pricing.json | 2 +- resources/data/content/fr/pricing.json | 2 +- resources/data/content/id/pricing.json | 2 +- resources/data/content/it/pricing.json | 2 +- resources/data/content/ja/pricing.json | 2 +- resources/data/content/ko/pricing.json | 2 +- resources/data/content/pt-BR/pricing.json | 2 +- resources/data/content/vi/pricing.json | 2 +- resources/data/content/zh-Hans/pricing.json | 2 +- resources/data/content/zh-Hant/pricing.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/data/content/de/pricing.json b/resources/data/content/de/pricing.json index e174c9ab..7782c2fb 100644 --- a/resources/data/content/de/pricing.json +++ b/resources/data/content/de/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Funktionieren die kostenpflichtigen Funktionen unter Linux?", - "answer": "Für Linux gilt dasselbe Lizenzmodell wie für den Mac. Die kostenpflichtigen Funktionen auf der Preisseite sind vorerst nur auf dem Mac verfügbar und kommen später für Linux." + "answer": "Die kostenpflichtigen Funktionen in der Tabelle oben gibt es vorerst nur auf dem Mac, spätere Versionen bringen sie auf Linux. Eine Lizenz gilt für alle Plattformen." } } }, diff --git a/resources/data/content/en/pricing.json b/resources/data/content/en/pricing.json index 1a114e86..c2b973ee 100644 --- a/resources/data/content/en/pricing.json +++ b/resources/data/content/en/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Do paid features work on Linux?", - "answer": "Linux follows the same licensing model as the Mac. The paid features listed on the Pricing page are Mac-only for now and come to Linux later." + "answer": "The paid features in the table above are Mac only for now and come to Linux in later releases. One license covers every platform." } } }, diff --git a/resources/data/content/es/pricing.json b/resources/data/content/es/pricing.json index fa896aff..c428ae6b 100644 --- a/resources/data/content/es/pricing.json +++ b/resources/data/content/es/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "¿Las funciones de pago funcionan en Linux?", - "answer": "Linux sigue el mismo modelo de licencias que Mac. Las funciones de pago de la página de precios están disponibles solo en Mac por ahora y llegarán a Linux más adelante." + "answer": "Las funciones de pago de la tabla de arriba son solo para Mac por ahora y llegarán a Linux en próximas versiones. Una licencia sirve en todas las plataformas." } } }, diff --git a/resources/data/content/fr/pricing.json b/resources/data/content/fr/pricing.json index cf2748c0..e5783735 100644 --- a/resources/data/content/fr/pricing.json +++ b/resources/data/content/fr/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Les fonctions payantes fonctionnent-elles sur Linux ?", - "answer": "Linux suit le même modèle de licence que le Mac. Les fonctions payantes de la page Tarifs sont réservées au Mac pour le moment et arriveront sur Linux plus tard." + "answer": "Les fonctions payantes du tableau ci-dessus sont réservées au Mac pour l’instant et arriveront sur Linux dans de prochaines versions. Une licence couvre toutes les plateformes." } } }, diff --git a/resources/data/content/id/pricing.json b/resources/data/content/id/pricing.json index 8f58964e..ba659edc 100644 --- a/resources/data/content/id/pricing.json +++ b/resources/data/content/id/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Apakah fitur berbayar berfungsi di Linux?", - "answer": "Linux mengikuti model lisensi yang sama dengan Mac. Fitur berbayar pada halaman Harga saat ini hanya tersedia di Mac dan akan hadir di Linux nanti." + "answer": "Fitur berbayar pada tabel di atas untuk sementara hanya ada di Mac dan akan hadir di Linux pada rilis berikutnya. Satu lisensi mencakup semua platform." } } }, diff --git a/resources/data/content/it/pricing.json b/resources/data/content/it/pricing.json index f037775b..690da5ab 100644 --- a/resources/data/content/it/pricing.json +++ b/resources/data/content/it/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Le funzioni a pagamento funzionano su Linux?", - "answer": "Linux segue lo stesso modello di licenza del Mac. Le funzioni a pagamento della pagina Prezzi sono per ora disponibili solo sul Mac e arriveranno su Linux in seguito." + "answer": "Le funzioni a pagamento nella tabella qui sopra per ora sono solo per Mac e arriveranno su Linux nelle prossime versioni. Una licenza vale per tutte le piattaforme." } } }, diff --git a/resources/data/content/ja/pricing.json b/resources/data/content/ja/pricing.json index c3d0ec0d..d3aaae68 100644 --- a/resources/data/content/ja/pricing.json +++ b/resources/data/content/ja/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "有料機能は Linux で使えますか?", - "answer": "Linux は Mac と同じライセンスモデルです。料金ページの有料機能は現在 Mac のみで利用でき、Linux には今後追加されます。" + "answer": "上の表の有料機能は現在 Mac のみで、今後のリリースで Linux にも対応します。1 つのライセンスですべてのプラットフォームに使えます。" } } }, diff --git a/resources/data/content/ko/pricing.json b/resources/data/content/ko/pricing.json index 35499014..6ea53629 100644 --- a/resources/data/content/ko/pricing.json +++ b/resources/data/content/ko/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "유료 기능을 Linux에서 사용할 수 있나요?", - "answer": "Linux는 Mac과 같은 라이선스 모델을 따릅니다. 요금 페이지의 유료 기능은 현재 Mac에서만 사용할 수 있으며 Linux에는 나중에 추가됩니다." + "answer": "위 표의 유료 기능은 현재 Mac에서만 사용할 수 있으며, 이후 릴리스에서 Linux에도 제공됩니다. 라이선스 하나로 모든 플랫폼에서 사용할 수 있습니다." } } }, diff --git a/resources/data/content/pt-BR/pricing.json b/resources/data/content/pt-BR/pricing.json index b98c2282..4a38b3dd 100644 --- a/resources/data/content/pt-BR/pricing.json +++ b/resources/data/content/pt-BR/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Os recursos pagos funcionam no Linux?", - "answer": "O Linux segue o mesmo modelo de licenciamento do Mac. Os recursos pagos da página de preços estão disponíveis apenas no Mac por enquanto e chegarão ao Linux depois." + "answer": "Os recursos pagos da tabela acima são só para Mac por enquanto e chegam ao Linux em versões futuras. Uma licença vale para todas as plataformas." } } }, diff --git a/resources/data/content/vi/pricing.json b/resources/data/content/vi/pricing.json index 030d6202..f38f0723 100644 --- a/resources/data/content/vi/pricing.json +++ b/resources/data/content/vi/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "Tính năng trả phí có dùng được trên Linux không?", - "answer": "Linux dùng cùng mô hình license với Mac. Các tính năng trả phí trên trang Giá hiện chỉ có trên Mac và sẽ có trên Linux sau." + "answer": "Các tính năng trả phí trong bảng ở trên hiện chỉ có trên Mac và sẽ có trên Linux ở các phiên bản sau. Một license dùng được trên mọi nền tảng." } } }, diff --git a/resources/data/content/zh-Hans/pricing.json b/resources/data/content/zh-Hans/pricing.json index 02270372..d91ae40b 100644 --- a/resources/data/content/zh-Hans/pricing.json +++ b/resources/data/content/zh-Hans/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "付费功能可以在 Linux 上使用吗?", - "answer": "Linux 采用与 Mac 相同的许可模式。定价页面列出的付费功能目前仅限 Mac,以后将加入 Linux。" + "answer": "上方表格中的付费功能目前仅限 Mac 使用,后续版本将支持 Linux。一个许可证适用于所有平台。" } } }, diff --git a/resources/data/content/zh-Hant/pricing.json b/resources/data/content/zh-Hant/pricing.json index a5627560..0b2b5fc9 100644 --- a/resources/data/content/zh-Hant/pricing.json +++ b/resources/data/content/zh-Hant/pricing.json @@ -47,7 +47,7 @@ }, "linux": { "question": "付費功能可以在 Linux 上使用嗎?", - "answer": "Linux 採用與 Mac 相同的授權模式。定價頁面列出的付費功能目前僅限 Mac,日後將加入 Linux。" + "answer": "上方表格中的付費功能目前僅限 Mac 使用,後續版本將支援 Linux。一個授權適用於所有平台。" } } },