From 19d47cadeeb67b8a20aef2ad940a8aeae6330e34 Mon Sep 17 00:00:00 2001 From: maruson08 Date: Wed, 26 Aug 2026 20:46:41 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8E=80[Style]=20Unify=20metadata=20so?= =?UTF-8?q?urce=20cards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/i18n.js | 4 +++- js/locales/metadata-ux.js | 26 ++++++++++++++++++++++++++ tests/i18n-quality.test.mjs | 2 +- tests/image-metadata.test.mjs | 8 ++++++++ tests/pdf-metadata.test.mjs | 5 +++++ tools/image/metadata/app.js | 24 ++++++++++++++++++------ tools/image/metadata/index.html | 2 +- tools/pdf/metadata/app.js | 10 +++++++--- tools/pdf/metadata/index.html | 2 +- 9 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 js/locales/metadata-ux.js diff --git a/js/i18n.js b/js/i18n.js index d9902f9..26480a1 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -8,6 +8,7 @@ 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"; +import { metadataUxLocales } from "./locales/metadata-ux.js"; const STORAGE_KEY = "secure-tools-language"; const baseTranslations = { en, ko, ja, es, de, fr }; @@ -18,7 +19,8 @@ export const translations = Object.fromEntries(Object.entries(baseTranslations). categories: { ...catalog.categories, image: { ...catalog.categories.image, metadata: imageMetadataLocales[language].categoryDescription } }, imageResize: imageResizeLocales[language].copy, imageCompressor: imageCompressorLocales[language].copy, - imageMetadata: imageMetadataLocales[language].copy, + imageMetadata: { ...imageMetadataLocales[language].copy, source: { ...imageMetadataLocales[language].copy.source, ...metadataUxLocales[language].image.source } }, + pdfMetadata: { ...catalog.pdfMetadata, source: { ...catalog.pdfMetadata.source, ...metadataUxLocales[language].pdf.source } }, privacyHub: privacyHubLocales[language].copy, }])); diff --git a/js/locales/metadata-ux.js b/js/locales/metadata-ux.js new file mode 100644 index 0000000..dfacd68 --- /dev/null +++ b/js/locales/metadata-ux.js @@ -0,0 +1,26 @@ +export const metadataUxLocales = { + en: { + image: { source: { selectedLabel: "Selected source image", meta: "{format} · {size}", remove: "Remove source image" } }, + pdf: { source: { selectedLabel: "Selected source PDF", meta: "PDF · {size}", remove: "Remove source PDF" } }, + }, + ko: { + image: { source: { selectedLabel: "선택한 원본 이미지", meta: "{format} · {size}", remove: "원본 이미지 제거" } }, + pdf: { source: { selectedLabel: "선택한 원본 PDF", meta: "PDF · {size}", remove: "원본 PDF 제거" } }, + }, + ja: { + image: { source: { selectedLabel: "選択した元画像", meta: "{format} · {size}", remove: "元画像を削除" } }, + pdf: { source: { selectedLabel: "選択した元PDF", meta: "PDF · {size}", remove: "元PDFを削除" } }, + }, + es: { + image: { source: { selectedLabel: "Imagen de origen seleccionada", meta: "{format} · {size}", remove: "Quitar imagen de origen" } }, + pdf: { source: { selectedLabel: "PDF de origen seleccionado", meta: "PDF · {size}", remove: "Quitar PDF de origen" } }, + }, + de: { + image: { source: { selectedLabel: "Ausgewähltes Quellbild", meta: "{format} · {size}", remove: "Quellbild entfernen" } }, + pdf: { source: { selectedLabel: "Ausgewählte Quell-PDF", meta: "PDF · {size}", remove: "Quell-PDF entfernen" } }, + }, + fr: { + image: { source: { selectedLabel: "Image source sélectionnée", meta: "{format} · {size}", remove: "Retirer l’image source" } }, + pdf: { source: { selectedLabel: "PDF source sélectionné", meta: "PDF · {size}", remove: "Retirer le PDF source" } }, + }, +}; diff --git a/tests/i18n-quality.test.mjs b/tests/i18n-quality.test.mjs index e4d2898..820fdb5 100644 --- a/tests/i18n-quality.test.mjs +++ b/tests/i18n-quality.test.mjs @@ -45,7 +45,7 @@ function placeholders(value) { function testCatalogParityAndQuality() { assert.deepEqual([...Object.keys(translations)], [...languageNames.keys()]); const english = flatten(translations.en); - assert.equal(english.size, 724); + assert.equal(english.size, 730); for (const [language, catalog] of Object.entries(translations)) { const flattened = flatten(catalog); diff --git a/tests/image-metadata.test.mjs b/tests/image-metadata.test.mjs index abf9805..1a599b6 100644 --- a/tests/image-metadata.test.mjs +++ b/tests/image-metadata.test.mjs @@ -148,6 +148,14 @@ await assert.rejects(cleanAndVerifyImageMetadata({ bytes: sourceBytes, cleanable const html = read("tools/image/metadata/index.html"); const app = read("tools/image/metadata/app.js"); const adapter = read("tools/image/metadata/metadata.js"); const model = read("tools/image/metadata/model.js"); const category = read("tools/image/index.html"); assert.match(html, /type="file"[^>]*aria-describedby="drop-description"/); assert.doesNotMatch(html, /type="file"[^>]*multiple/); +assert.match(html, /id="source-card" class="source-card"[^>]*data-i18n-aria-label="imageMetadata\.source\.selectedLabel"[^>]*hidden/); +assert.match(html, /id="source-thumbnail" class="queue-thumbnail" alt=""/); +assert.match(html, /id="source-name" class="source-name"/); +assert.match(html, /id="clear-source" class="queue-action queue-action--remove"[^>]*data-i18n-aria-label="imageMetadata\.source\.remove"/); +assert.match(app, /URL\.createObjectURL\(state\.source\.file\)/); +assert.match(app, /URL\.revokeObjectURL\(state\.previewUrl\)/); +assert.match(app, /pagehide[^;]+releasePreview/); +assert.match(app, /releasePreview\(\); state\.source = null; state\.inspection = null; state\.result = null/); assert.match(html, /connect-src 'none'/); assert.match(html, /role="status" aria-live="polite"/); assert.match(category, /href="\.\/metadata\/"/); assert.equal((category.match(/class="category-tool surface"/g) || []).length, 4); const requestIndex = app.indexOf("await requestSaveHandle"); const cleanIndex = app.indexOf("await cleanAndVerifyImageMetadata"); const writeIndex = app.indexOf("await writeBlobToHandle"); diff --git a/tests/pdf-metadata.test.mjs b/tests/pdf-metadata.test.mjs index 0ddf719..c6edbc7 100644 --- a/tests/pdf-metadata.test.mjs +++ b/tests/pdf-metadata.test.mjs @@ -145,6 +145,11 @@ function testUiArchitectureAndScope() { const vendor = JSON.parse(read("assets/vendor/pdf-lib/package.json")); assert.equal(vendor.version, "1.17.1"); assert.match(html, /