From 6b3f052c8d995de54861eca13f7ed76e87503803 Mon Sep 17 00:00:00 2001 From: maruson08 Date: Wed, 26 Aug 2026 15:33:46 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9B[Fix]=20Repair=20image=20catego?= =?UTF-8?q?ry=20tool=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/image/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/image/index.html b/tools/image/index.html index 08f8988..c5a842c 100644 --- a/tools/image/index.html +++ b/tools/image/index.html @@ -104,7 +104,6 @@

Image Compressor

Reduce file size with clear quality controls.

-
  • +

    Available tools process file contents in browser memory. Planned items are clearly marked.

    From 2c8fe405dfe81076e68b9235dba2a99c27cc1529 Mon Sep 17 00:00:00 2001 From: maruson08 Date: Wed, 26 Aug 2026 18:08:56 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8[Feat]=20Promote=20privacy=20metad?= =?UTF-8?q?ata=20tool=20hub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/i18n.js | 6 ++- js/locales/privacy-hub.js | 80 +++++++++++++++++++++++++++++++++++++++ tools/privacy/index.html | 4 +- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 js/locales/privacy-hub.js diff --git a/js/i18n.js b/js/i18n.js index eb8bc91..d9902f9 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -7,17 +7,19 @@ import { fr } from "./locales/fr.js"; import { imageResizeLocales } from "./locales/image-resize.js"; import { imageCompressorLocales } from "./locales/image-compressor.js"; import { imageMetadataLocales } from "./locales/image-metadata.js"; +import { privacyHubLocales } from "./locales/privacy-hub.js"; const STORAGE_KEY = "secure-tools-language"; const baseTranslations = { en, ko, ja, es, de, fr }; export const translations = Object.fromEntries(Object.entries(baseTranslations).map(([language, catalog]) => [language, { ...catalog, - metadata: { ...catalog.metadata, imageResize: imageResizeLocales[language].metadata, imageCompressor: imageCompressorLocales[language].metadata, imageMetadata: imageMetadataLocales[language].metadata }, - tools: { ...catalog.tools, imageMetadata: imageMetadataLocales[language].toolName }, + metadata: { ...catalog.metadata, imageResize: imageResizeLocales[language].metadata, imageCompressor: imageCompressorLocales[language].metadata, imageMetadata: imageMetadataLocales[language].metadata, privacyCategory: privacyHubLocales[language].metadata }, + tools: { ...catalog.tools, imageMetadata: imageMetadataLocales[language].toolName, categoryDescriptions: { ...catalog.tools.categoryDescriptions, privacy: privacyHubLocales[language].categoryDescription } }, categories: { ...catalog.categories, image: { ...catalog.categories.image, metadata: imageMetadataLocales[language].categoryDescription } }, imageResize: imageResizeLocales[language].copy, imageCompressor: imageCompressorLocales[language].copy, imageMetadata: imageMetadataLocales[language].copy, + privacyHub: privacyHubLocales[language].copy, }])); export function resolveLanguage(value, availableLanguages = Object.keys(translations)) { diff --git a/js/locales/privacy-hub.js b/js/locales/privacy-hub.js new file mode 100644 index 0000000..5cf576d --- /dev/null +++ b/js/locales/privacy-hub.js @@ -0,0 +1,80 @@ +export const privacyHubLocales = { + en: { + metadata: { title: "Privacy metadata tools — Secure Tools", description: "Choose a specialized local tool for supported image or PDF metadata." }, + categoryDescription: "Inspect and clean supported image or PDF metadata.", + copy: { + title: "Privacy metadata tools", + description: "Choose the tool that matches your file type. Image and PDF metadata have different supported scopes.", + imageTitle: "Image Metadata Inspector & Cleaner", + imageDescription: "Inspect decoded and opaque metadata in JPEG, PNG, or WebP images, then save a verified Privacy Clean copy. Inspection may be partial and non-exhaustive.", + pdfTitle: "PDF Metadata Inspector & Cleaner", + pdfDescription: "Inspect and remove supported PDF document-info fields. This does not cover every XMP packet, attachment, annotation, or hidden document structure.", + note: "These specialized tools process files locally and verify only their documented supported scope.", + }, + }, + ko: { + metadata: { title: "개인정보 메타데이터 도구 — Secure Tools", description: "지원되는 이미지 또는 PDF 메타데이터에 맞는 로컬 도구를 선택하세요." }, + categoryDescription: "지원되는 이미지 또는 PDF 메타데이터를 검사하고 정리합니다.", + copy: { + title: "개인정보 메타데이터 도구", + description: "파일 형식에 맞는 도구를 선택하세요. 이미지와 PDF 메타데이터는 지원 범위가 서로 다릅니다.", + imageTitle: "이미지 메타데이터 검사 및 정리", + imageDescription: "JPEG, PNG 또는 WebP의 해석된 메타데이터와 불투명 메타데이터를 검사한 뒤 검증된 개인정보 정리본을 저장합니다. 검사는 부분적이며 완전하지 않을 수 있습니다.", + pdfTitle: "PDF 메타데이터 검사 및 정리", + pdfDescription: "지원되는 PDF 문서 정보 필드를 검사하고 제거합니다. 모든 XMP 패킷, 첨부 파일, 주석 또는 숨겨진 문서 구조를 다루지는 않습니다.", + note: "각 전문 도구는 파일을 로컬에서 처리하며 문서화된 지원 범위만 검증합니다.", + }, + }, + ja: { + metadata: { title: "プライバシーメタデータツール — Secure Tools", description: "対応する画像またはPDFメタデータ用のローカルツールを選択します。" }, + categoryDescription: "対応する画像またはPDFのメタデータを検査・整理します。", + copy: { + title: "プライバシーメタデータツール", + description: "ファイル形式に合うツールを選択してください。画像とPDFでは対応するメタデータの範囲が異なります。", + imageTitle: "画像メタデータ検査・クリーナー", + imageDescription: "JPEG、PNG、WebPの解読済みおよび不透明なメタデータを検査し、検証済みのプライバシークリーンコピーを保存します。検査は部分的で網羅的でない場合があります。", + pdfTitle: "PDFメタデータ検査・クリーナー", + pdfDescription: "対応するPDF文書情報フィールドを検査・削除します。すべてのXMPパケット、添付、注釈、隠れた文書構造を対象とするものではありません。", + note: "各専用ツールはファイルをローカルで処理し、文書化された対応範囲のみを検証します。", + }, + }, + es: { + metadata: { title: "Herramientas de metadatos privados — Secure Tools", description: "Elige una herramienta local especializada para metadatos compatibles de imagen o PDF." }, + categoryDescription: "Inspecciona y limpia metadatos compatibles de imágenes o PDF.", + copy: { + title: "Herramientas de metadatos privados", + description: "Elige la herramienta adecuada para el tipo de archivo. Las imágenes y los PDF tienen alcances de metadatos distintos.", + imageTitle: "Inspector y limpiador de metadatos de imagen", + imageDescription: "Inspecciona metadatos decodificados y opacos en imágenes JPEG, PNG o WebP y guarda una copia de privacidad verificada. La inspección puede ser parcial y no exhaustiva.", + pdfTitle: "Inspector y limpiador de metadatos PDF", + pdfDescription: "Inspecciona y elimina campos compatibles de información del documento PDF. No abarca todos los paquetes XMP, adjuntos, anotaciones ni estructuras ocultas.", + note: "Estas herramientas especializadas procesan los archivos localmente y solo verifican su alcance compatible documentado.", + }, + }, + de: { + metadata: { title: "Datenschutz-Metadatenwerkzeuge — Secure Tools", description: "Ein spezialisiertes lokales Werkzeug für unterstützte Bild- oder PDF-Metadaten wählen." }, + categoryDescription: "Unterstützte Bild- oder PDF-Metadaten prüfen und bereinigen.", + copy: { + title: "Datenschutz-Metadatenwerkzeuge", + description: "Wählen Sie das Werkzeug passend zum Dateityp. Bild- und PDF-Metadaten haben unterschiedliche unterstützte Bereiche.", + imageTitle: "Bildmetadaten-Prüfer & Bereiniger", + imageDescription: "Dekodierte und undurchsichtige Metadaten in JPEG-, PNG- oder WebP-Bildern prüfen und eine verifizierte Datenschutzkopie speichern. Die Prüfung kann teilweise und nicht vollständig sein.", + pdfTitle: "PDF-Metadaten-Prüfer & Bereiniger", + pdfDescription: "Unterstützte PDF-Dokumentinformationsfelder prüfen und entfernen. Dies umfasst nicht jedes XMP-Paket, jeden Anhang, jede Anmerkung oder verborgene Dokumentstruktur.", + note: "Diese spezialisierten Werkzeuge verarbeiten Dateien lokal und verifizieren nur ihren dokumentierten unterstützten Umfang.", + }, + }, + fr: { + metadata: { title: "Outils de métadonnées privées — Secure Tools", description: "Choisissez un outil local spécialisé pour les métadonnées d’image ou PDF prises en charge." }, + categoryDescription: "Inspectez et nettoyez les métadonnées d’image ou PDF prises en charge.", + copy: { + title: "Outils de métadonnées privées", + description: "Choisissez l’outil adapté au type de fichier. Les images et les PDF ont des périmètres de métadonnées différents.", + imageTitle: "Inspecteur et nettoyeur de métadonnées d’image", + imageDescription: "Inspectez les métadonnées décodées et opaques des images JPEG, PNG ou WebP, puis enregistrez une copie de confidentialité vérifiée. L’inspection peut être partielle et non exhaustive.", + pdfTitle: "Inspecteur et nettoyeur de métadonnées PDF", + pdfDescription: "Inspectez et supprimez les champs d’information PDF pris en charge. Cela ne couvre pas tous les paquets XMP, pièces jointes, annotations ou structures cachées.", + note: "Ces outils spécialisés traitent les fichiers localement et vérifient uniquement leur périmètre documenté pris en charge.", + }, + }, +}; diff --git a/tools/privacy/index.html b/tools/privacy/index.html index e10d993..28bcda8 100644 --- a/tools/privacy/index.html +++ b/tools/privacy/index.html @@ -1,6 +1,6 @@ - Privacy tools — Secure Tools + Privacy metadata tools — Secure Tools -

    Tool category

    Privacy tools

    Inspect and remove hidden file details without sharing the source file.

    • Coming soon

      Metadata Inspector

      See what identifying information a file contains.

    • Coming soon

      Metadata Cleaner

      Create a copy with supported metadata removed.

    This category is planned. No unavailable item is presented as working.

    +
    From 801153d7a079d409cd73c37ecf96fe50303fbc60 Mon Sep 17 00:00:00 2001 From: maruson08 Date: Wed, 26 Aug 2026 18:12:08 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=85[Test]=20Cover=20category=20routes?= =?UTF-8?q?=20and=20availability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/category-availability.test.mjs | 66 +++++++++++++++++++++++++ tests/i18n-quality.test.mjs | 2 +- tests/pdf-merge-and-categories.test.mjs | 10 ++-- tests/run-all.mjs | 1 + tests/ux-consistency.test.mjs | 3 +- 5 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 tests/category-availability.test.mjs diff --git a/tests/category-availability.test.mjs b/tests/category-availability.test.mjs new file mode 100644 index 0000000..1db9f89 --- /dev/null +++ b/tests/category-availability.test.mjs @@ -0,0 +1,66 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { translations } from "../js/i18n.js"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const read = (relative) => fs.readFileSync(path.join(root, relative), "utf8"); + +function categoryList(html) { + const list = html.match(/