@jjlmoya/utils-audiovisual 1.19.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/package.json +4 -2
  2. package/src/category/i18n/de.ts +1 -1
  3. package/src/category/i18n/fr.ts +1 -1
  4. package/src/category/i18n/ru.ts +1 -1
  5. package/src/layouts/PreviewLayout.astro +7 -2
  6. package/src/tests/diacritics_density.test.ts +118 -0
  7. package/src/tests/inverted_punctuation.test.ts +84 -0
  8. package/src/tests/no_en_dash.test.ts +70 -0
  9. package/src/tests/pagespeed_best_practices.test.ts +198 -0
  10. package/src/tests/script_density.test.ts +94 -0
  11. package/src/tool/chromaticLens/component.astro +2 -2
  12. package/src/tool/chromaticLens/i18n/de.ts +6 -6
  13. package/src/tool/chromaticLens/i18n/fr.ts +3 -3
  14. package/src/tool/chromaticLens/i18n/pl.ts +1 -1
  15. package/src/tool/chromaticLens/i18n/ru.ts +10 -10
  16. package/src/tool/chromaticLens/i18n/zh.ts +2 -2
  17. package/src/tool/collageMaker/component.astro +3 -3
  18. package/src/tool/collageMaker/i18n/de.ts +6 -6
  19. package/src/tool/collageMaker/i18n/fr.ts +4 -4
  20. package/src/tool/collageMaker/i18n/pl.ts +5 -5
  21. package/src/tool/collageMaker/i18n/ru.ts +12 -12
  22. package/src/tool/collageMaker/i18n/sv.ts +3 -3
  23. package/src/tool/collageMaker/i18n/zh.ts +1 -1
  24. package/src/tool/depthOfFieldCalculator/component.astro +1 -1
  25. package/src/tool/depthOfFieldCalculator/i18n/de.ts +3 -3
  26. package/src/tool/depthOfFieldCalculator/i18n/en.ts +7 -7
  27. package/src/tool/depthOfFieldCalculator/i18n/es.ts +2 -2
  28. package/src/tool/depthOfFieldCalculator/i18n/fr.ts +6 -6
  29. package/src/tool/depthOfFieldCalculator/i18n/id.ts +2 -2
  30. package/src/tool/depthOfFieldCalculator/i18n/it.ts +2 -2
  31. package/src/tool/depthOfFieldCalculator/i18n/ja.ts +1 -1
  32. package/src/tool/depthOfFieldCalculator/i18n/ko.ts +1 -1
  33. package/src/tool/depthOfFieldCalculator/i18n/nl.ts +2 -2
  34. package/src/tool/depthOfFieldCalculator/i18n/pl.ts +2 -2
  35. package/src/tool/depthOfFieldCalculator/i18n/pt.ts +2 -2
  36. package/src/tool/depthOfFieldCalculator/i18n/ru.ts +6 -6
  37. package/src/tool/depthOfFieldCalculator/i18n/sv.ts +2 -2
  38. package/src/tool/depthOfFieldCalculator/i18n/tr.ts +1 -1
  39. package/src/tool/depthOfFieldCalculator/i18n/zh.ts +3 -3
  40. package/src/tool/exifCleaner/component.astro +1 -1
  41. package/src/tool/exifCleaner/i18n/de.ts +8 -8
  42. package/src/tool/exifCleaner/i18n/fr.ts +11 -11
  43. package/src/tool/exifCleaner/i18n/pl.ts +6 -6
  44. package/src/tool/exifCleaner/i18n/ru.ts +14 -14
  45. package/src/tool/exifCleaner/i18n/zh.ts +3 -3
  46. package/src/tool/imageCompressor/component.astro +6 -4
  47. package/src/tool/imageCompressor/i18n/de.ts +16 -16
  48. package/src/tool/imageCompressor/i18n/fr.ts +8 -8
  49. package/src/tool/imageCompressor/i18n/pl.ts +1 -1
  50. package/src/tool/imageCompressor/i18n/ru.ts +9 -9
  51. package/src/tool/imageCompressor/i18n/zh.ts +1 -1
  52. package/src/tool/printQualityCalculator/component.astro +118 -110
  53. package/src/tool/printQualityCalculator/i18n/de.ts +5 -5
  54. package/src/tool/printQualityCalculator/i18n/fr.ts +11 -11
  55. package/src/tool/printQualityCalculator/i18n/pl.ts +4 -4
  56. package/src/tool/printQualityCalculator/i18n/ru.ts +11 -11
  57. package/src/tool/printQualityCalculator/i18n/zh.ts +4 -4
  58. package/src/tool/printQualityCalculator/print-quality-calculator-pixels-to-cm-dpi.css +193 -40
  59. package/src/tool/privacyBlur/component.astro +2 -2
  60. package/src/tool/privacyBlur/i18n/de.ts +5 -5
  61. package/src/tool/privacyBlur/i18n/fr.ts +9 -9
  62. package/src/tool/privacyBlur/i18n/ru.ts +6 -6
  63. package/src/tool/subtitleSync/component.astro +2 -2
  64. package/src/tool/subtitleSync/i18n/de.ts +1 -1
  65. package/src/tool/subtitleSync/i18n/fr.ts +9 -9
  66. package/src/tool/subtitleSync/i18n/ru.ts +6 -6
  67. package/src/tool/subtitleSync/i18n/sv.ts +4 -4
  68. package/src/tool/timelapseCalculator/i18n/fr.ts +6 -6
  69. package/src/tool/timelapseCalculator/i18n/ru.ts +3 -3
  70. package/src/tool/timelapseCalculator/i18n/zh.ts +4 -4
  71. package/src/tool/tvDistance/component.astro +1 -1
  72. package/src/tool/tvDistance/i18n/fr.ts +2 -2
  73. package/src/tool/tvDistance/i18n/ru.ts +9 -9
  74. package/src/tool/tvDistance/i18n/zh.ts +4 -4
  75. package/src/tool/videoFrameExtractor/component.astro +3 -3
  76. package/src/tool/videoFrameExtractor/i18n/fr.ts +8 -8
  77. package/src/tool/videoFrameExtractor/i18n/ru.ts +2 -2
  78. package/src/tool/videoMerger/component.astro +3 -3
  79. package/src/tool/videoMerger/i18n/de.ts +1 -1
  80. package/src/tool/videoMerger/i18n/fr.ts +6 -6
@@ -55,7 +55,7 @@ const howTo: ImageCompressorLocaleContent['howTo'] = [
55
55
  },
56
56
  {
57
57
  name: "Qualität anpassen",
58
- text: "Verwenden Sie den Schieberegler, um das perfekte Gleichgewicht zwischen Dateigröße und visueller Qualität zu finden (empfohlen: 7585 %).",
58
+ text: "Verwenden Sie den Schieberegler, um das perfekte Gleichgewicht zwischen Dateigröße und visueller Qualität zu finden (empfohlen: 75-85 %).",
59
59
  },
60
60
  {
61
61
  name: "Größe ändern (optional)",
@@ -73,13 +73,13 @@ const seo: ImageCompressorLocaleContent['seo'] = [
73
73
  title: 'Professionelle Web Bildoptimierung',
74
74
  items: [
75
75
  'Intelligente JPG-, PNG- und WebP-Komprimierung',
76
- 'Gewicht um 5080 % reduzieren bei Beibehaltung der visuellen Qualität',
77
- '100 % lokale Verarbeitung Privatsphäre garantiert',
76
+ 'Gewicht um 50-80 % reduzieren bei Beibehaltung der visuellen Qualität',
77
+ '100 % lokale Verarbeitung - Privatsphäre garantiert',
78
78
  'Core Web Vitals und SEO-Positionierung verbessern'
79
79
  ]
80
80
  },
81
81
  { type: 'title', text: 'Bildoptimierung: Web Geschwindigkeit und Core Web Vitals', level: 2 },
82
- { type: 'paragraph', html: 'In der Ära der digitalen Unmittelbarkeit verliert eine langsame Website Nutzer. Nicht optimierte Bilder machen 6070 % des Gesamtgewichts einer Webseite aus. Sie zu optimieren ist der erste Schritt, um Ihre Google-Metriken (LCP, CLS) und Ihre Positionierung in den Suchergebnissen zu verbessern.' },
82
+ { type: 'paragraph', html: 'In der Ära der digitalen Unmittelbarkeit verliert eine langsame Website Nutzer. Nicht optimierte Bilder machen 60-70 % des Gesamtgewichts einer Webseite aus. Sie zu optimieren ist der erste Schritt, um Ihre Google-Metriken (LCP, CLS) und Ihre Positionierung in den Suchergebnissen zu verbessern.' },
83
83
 
84
84
  { type: 'stats', items: [
85
85
  { value: '50-80%', label: 'Typische Gewichtsreduktion', icon: 'mdi:trending-down' },
@@ -89,22 +89,22 @@ const seo: ImageCompressorLocaleContent['seo'] = [
89
89
 
90
90
  { type: 'title', text: 'Erklärung der Komprimierungsformate', level: 3 },
91
91
  { type: 'table', headers: ['Format', 'Komprimierung', 'Anwendungsfälle', 'Kompatibilität'], rows: [
92
- ['JPEG', 'Verlustbehaftet 5090 %', 'Kamerafotos, redaktionelle Inhalte', 'Universal (100 %)'],
93
- ['PNG', 'Verlustfrei 3050 %', 'Grafiken, Logos, Transparenzen', 'Universal (100 %)'],
94
- ['WebP', 'Verlustbehaftet/Verlustfrei 2535 % mehr', 'Modernes Web, soziale Netzwerke', '95 % moderne Browser'],
92
+ ['JPEG', 'Verlustbehaftet 50-90 %', 'Kamerafotos, redaktionelle Inhalte', 'Universal (100 %)'],
93
+ ['PNG', 'Verlustfrei 30-50 %', 'Grafiken, Logos, Transparenzen', 'Universal (100 %)'],
94
+ ['WebP', 'Verlustbehaftet/Verlustfrei 25-35 % mehr', 'Modernes Web, soziale Netzwerke', '95 % moderne Browser'],
95
95
  ['AVIF', 'Verlustbehaftet/Verlustfrei 20 % Verbesserung', 'Next-Generation-Web', 'Nur neue Browser']
96
96
  ] },
97
97
 
98
- { type: 'card', title: 'Warum WebP die Zukunft ist', html: 'Google hat WebP speziell für das Web entwickelt. Es bietet eine überlegene Komprimierung gegenüber JPEG und PNG bei gleichbleibender oder verbesserter visueller Qualität. Es ist 2535 % kleiner als äquivalente JPEGs. Moderne Browser unterstützen es zu 95 %.' },
98
+ { type: 'card', title: 'Warum WebP die Zukunft ist', html: 'Google hat WebP speziell für das Web entwickelt. Es bietet eine überlegene Komprimierung gegenüber JPEG und PNG bei gleichbleibender oder verbesserter visueller Qualität. Es ist 25-35 % kleiner als äquivalente JPEGs. Moderne Browser unterstützen es zu 95 %.' },
99
99
 
100
100
  { type: 'title', text: 'Verlustbehaftete vs. verlustfreie Komprimierung', level: 3 },
101
101
  { type: 'comparative', items: [
102
102
  {
103
103
  title: 'Verlustbehaftete Komprimierung',
104
- description: 'JPG, WebP Entfernt unmerkliche visuelle Informationen',
104
+ description: 'JPG, WebP - Entfernt unmerkliche visuelle Informationen',
105
105
  icon: 'mdi:compress',
106
106
  points: [
107
- 'Reduziert 7090 % des ursprünglichen Gewichts',
107
+ 'Reduziert 70-90 % des ursprünglichen Gewichts',
108
108
  'Für das menschliche Auge unmerklich, wenn die Qualität >75 % bleibt',
109
109
  'Ideal für realistische Fotografie',
110
110
  'Nicht empfohlen für Logos oder scharfen Text'
@@ -113,10 +113,10 @@ const seo: ImageCompressorLocaleContent['seo'] = [
113
113
  },
114
114
  {
115
115
  title: 'Verlustfreie Komprimierung',
116
- description: 'PNG, WebP verlustfrei Behält 100 % der visuellen Daten bei',
116
+ description: 'PNG, WebP verlustfrei - Behält 100 % der visuellen Daten bei',
117
117
  icon: 'mdi:shield',
118
118
  points: [
119
- 'Reduziert 2050 % des Gewichts',
119
+ 'Reduziert 20-50 % des Gewichts',
120
120
  'Perfekte Qualität, keine Verschlechterung',
121
121
  'Ideal für Grafiken, Logos, Transparenzen',
122
122
  'Schwerere Dateien als bei verlustbehafteter Komprimierung'
@@ -138,7 +138,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
138
138
  con: 'Erfordert Browser mit Canvas-API-Unterstützung (universell verfügbar)'
139
139
  },
140
140
  {
141
- pro: 'WebP ist 2535 % kleiner als JPEG bei gleicher Qualität',
141
+ pro: 'WebP ist 25-35 % kleiner als JPEG bei gleicher Qualität',
142
142
  con: 'Alte Versionen von Safari und IE unterstützen WebP nicht (Fallback verfügbar)'
143
143
  },
144
144
  {
@@ -147,7 +147,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
147
147
  },
148
148
  {
149
149
  pro: 'Optionales Resizing: Reduziert Auflösung zusätzlich zur Komprimierung',
150
- con: 'Resizing führt zu Informationsverlust besser die Auflösung an der Quelle optimieren'
150
+ con: 'Resizing führt zu Informationsverlust - besser die Auflösung an der Quelle optimieren'
151
151
  }
152
152
  ], proTitle: 'Vorteile', conTitle: 'Einschränkungen' },
153
153
 
@@ -156,7 +156,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
156
156
  { type: 'glossary', items: [
157
157
  {
158
158
  term: 'Verlustbehaftete Komprimierung',
159
- definition: 'Entfernt visuelle Daten, die das menschliche Auge als Rauschen wahrnimmt. Ideal für Fotografie. JPEG, verlustbehaftetes WebP, HEIC sind verlustbehaftet.'
159
+ definition: 'Entfernt visuelle Daten, die das menschliche Auge als \"Rauschen\" wahrnimmt. Ideal für Fotografie. JPEG, verlustbehaftetes WebP, HEIC sind verlustbehaftet.'
160
160
  },
161
161
  {
162
162
  term: 'Verlustfreie Komprimierung',
@@ -168,7 +168,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
168
168
  },
169
169
  {
170
170
  term: 'WebP',
171
- definition: 'Von Google entwickeltes Format. 2535 % kleiner als JPEG. Wird von 95 % der modernen Browser unterstützt (alle außer IE).'
171
+ definition: 'Von Google entwickeltes Format. 25-35 % kleiner als JPEG. Wird von 95 % der modernen Browser unterstützt (alle außer IE).'
172
172
  },
173
173
  {
174
174
  term: 'Komprimierungsartefakte',
@@ -55,7 +55,7 @@ const howTo: ImageCompressorLocaleContent['howTo'] = [
55
55
  },
56
56
  {
57
57
  name: "Ajuster la qualité",
58
- text: "Utilisez le curseur pour trouver l'équilibre parfait entre la taille du fichier et la qualité visuelle (recommandé : 75-85 %).",
58
+ text: "Utilisez le curseur pour trouver l'équilibre parfait entre la taille du fichier et la qualité visuelle (recommandé: 75-85 %).",
59
59
  },
60
60
  {
61
61
  name: "Redimensionner (optionnel)",
@@ -78,7 +78,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
78
78
  'Améliorez les Core Web Vitals et le positionnement SEO'
79
79
  ]
80
80
  },
81
- { type: 'title', text: 'Optimisation des Images : Vitesse Web et Core Web Vitals', level: 2 },
81
+ { type: 'title', text: 'Optimisation des Images: Vitesse Web et Core Web Vitals', level: 2 },
82
82
  { type: 'paragraph', html: 'À l\'ère de l\'immédiateté numérique, un site lent perd des utilisateurs. Les images non optimisées représentent 60 à 70 % du poids total d\'une page web. Les optimiser est la première étape pour améliorer vos métriques Google (LCP, CLS) et votre positionnement dans les résultats de recherche.' },
83
83
 
84
84
  { type: 'stats', items: [
@@ -134,7 +134,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
134
134
 
135
135
  { type: 'proscons', items: [
136
136
  {
137
- pro: 'Confidentialité totale : traitement 100 % local, sans serveurs cloud',
137
+ pro: 'Confidentialité totale: traitement 100 % local, sans serveurs cloud',
138
138
  con: 'Nécessite un navigateur supportant l\'API Canvas (c\'est universel)'
139
139
  },
140
140
  {
@@ -146,12 +146,12 @@ const seo: ImageCompressorLocaleContent['seo'] = [
146
146
  con: 'Les images très volumineuses (>50 Mo) peuvent nécessiter un délai'
147
147
  },
148
148
  {
149
- pro: 'Redimensionnement optionnel : réduit la résolution en plus de la compression',
149
+ pro: 'Redimensionnement optionnel: réduit la résolution en plus de la compression',
150
150
  con: 'Le redimensionnement entraîne une perte d\'information - mieux vaut optimiser à la source'
151
151
  }
152
152
  ], proTitle: 'Avantages', conTitle: 'Limitations' },
153
153
 
154
- { type: 'diagnostic', variant: 'warning', title: 'Attention : Une Compression Excessive Dégrade', icon: 'mdi:alert', badge: 'Qualité', html: 'Maintenez une qualité > 75 % pour la photographie et > 85 % pour le contenu éditorial. En dessous, les artefacts de compression (taches, bandes) deviennent visibles. Une image de belle apparence en vignette peut être hideuse en grand.' },
154
+ { type: 'diagnostic', variant: 'warning', title: 'Attention: Une Compression Excessive Dégrade', icon: 'mdi:alert', badge: 'Qualité', html: 'Maintenez une qualité > 75 % pour la photographie et > 85 % pour le contenu éditorial. En dessous, les artefacts de compression (taches, bandes) deviennent visibles. Une image de belle apparence en vignette peut être hideuse en grand.' },
155
155
 
156
156
  { type: 'glossary', items: [
157
157
  {
@@ -164,7 +164,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
164
164
  },
165
165
  {
166
166
  term: 'Core Web Vitals (Google)',
167
- definition: 'Indicateurs d\'expérience utilisateur : LCP (vitesse de chargement), FID (latence d\'interaction), CLS (stabilité visuelle). Affectent le SEO.'
167
+ definition: 'Indicateurs d\'expérience utilisateur: LCP (vitesse de chargement), FID (latence d\'interaction), CLS (stabilité visuelle). Affectent le SEO.'
168
168
  },
169
169
  {
170
170
  term: 'WebP',
@@ -172,11 +172,11 @@ const seo: ImageCompressorLocaleContent['seo'] = [
172
172
  },
173
173
  {
174
174
  term: 'Artefacts de Compression',
175
- definition: 'Défauts visuels causés par une compression excessive : taches, bandes de couleur, bords flous.'
175
+ definition: 'Défauts visuels causés par une compression excessive: taches, bandes de couleur, bords flous.'
176
176
  }
177
177
  ] },
178
178
 
179
- { type: 'message', title: 'Optimisation Web Professionnelle', ariaLabel: 'Informations sur l\'optimisation d\'images pour le SEO', html: 'Ce n\'est pas de la vanité technique : compresser les images est un investissement direct dans l\'expérience utilisateur et le classement Google. Chaque kilo-octet compte sur mobile. Notre outil transforme ce qui nécessitait auparavant un logiciel professionnel ($$$) en un processus gratuit en 3 clics.' },
179
+ { type: 'message', title: 'Optimisation Web Professionnelle', ariaLabel: 'Informations sur l\'optimisation d\'images pour le SEO', html: 'Ce n\'est pas de la vanité technique: compresser les images est un investissement direct dans l\'expérience utilisateur et le classement Google. Chaque kilo-octet compte sur mobile. Notre outil transforme ce qui nécessitait auparavant un logiciel professionnel ($$$) en un processus gratuit en 3 clics.' },
180
180
 
181
181
  { type: 'title', text: 'Prêt pour le Web Moderne', level: 3 },
182
182
  { type: 'paragraph', html: 'Utilisez la compression intelligente et le format WebP pour que votre présence en ligne soit rapide, responsive et compétitive dans les recherches.' }
@@ -156,7 +156,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
156
156
  { type: 'glossary', items: [
157
157
  {
158
158
  term: 'Kompresja Stratna (Lossy)',
159
- definition: 'Usuwa dane wizualne, które ludzkie oko postrzega jako szum”. Idealna dla fotografii. JPEG, stratny WebP, HEIC są kompresjami stratnymi.'
159
+ definition: 'Usuwa dane wizualne, które ludzkie oko postrzega jako \"szum\". Idealna dla fotografii. JPEG, stratny WebP, HEIC są kompresjami stratnymi.'
160
160
  },
161
161
  {
162
162
  term: 'Kompresja Bezstratna (Lossless)',
@@ -44,7 +44,7 @@ const faq: ImageCompressorLocaleContent['faq'] = [
44
44
  },
45
45
  {
46
46
  question: "Почему мне стоит конвертировать в WebP?",
47
- answer: "WebP это современный стандартный формат для интернета. Он предлагает более высокое качество, чем JPG и PNG, при весе на 30% меньше, что ускоряет загрузку страниц.",
47
+ answer: "WebP - это современный стандартный формат для интернета. Он предлагает более высокое качество, чем JPG и PNG, при весе на 30% меньше, что ускоряет загрузку страниц.",
48
48
  },
49
49
  ];
50
50
 
@@ -74,12 +74,12 @@ const seo: ImageCompressorLocaleContent['seo'] = [
74
74
  items: [
75
75
  'Интеллектуальное сжатие JPG, PNG и WebP',
76
76
  'Уменьшение веса на 50-80% при сохранении визуального качества',
77
- '100% локальная обработка конфиденциальность гарантирована',
77
+ '100% локальная обработка - конфиденциальность гарантирована',
78
78
  'Улучшение Core Web Vitals и позиций в SEO'
79
79
  ]
80
80
  },
81
81
  { type: 'title', text: 'Оптимизация изображений: скорость веба и Core Web Vitals', level: 2 },
82
- { type: 'paragraph', html: 'В эпоху цифровой мгновенности медленный веб-сайт теряет пользователей. Неоптимизированные изображения составляют 60-70% от общего веса веб-страницы. Их оптимизация это первый шаг к улучшению ваших метрик Google (LCP, CLS) и вашего позиционирования в результатах поиска.' },
82
+ { type: 'paragraph', html: 'В эпоху цифровой мгновенности медленный веб-сайт теряет пользователей. Неоптимизированные изображения составляют 60-70% от общего веса веб-страницы. Их оптимизация - это первый шаг к улучшению ваших метрик Google (LCP, CLS) и вашего позиционирования в результатах поиска.' },
83
83
 
84
84
  { type: 'stats', items: [
85
85
  { value: '50-80%', label: 'Типичное сокращение веса', icon: 'mdi:trending-down' },
@@ -95,13 +95,13 @@ const seo: ImageCompressorLocaleContent['seo'] = [
95
95
  ['AVIF', 'С потерями/без потерь на 20% лучше', 'Веб следующего поколения', 'Только новые браузеры']
96
96
  ] },
97
97
 
98
- { type: 'card', title: 'Почему WebP это будущее', html: 'Google разработал WebP специально для веба. Он предлагает лучшее сжатие, чем JPEG и PNG, сохраняя или улучшая визуальное качество. Он на 25-35% меньше эквивалентов JPEG. Современные браузеры поддерживают его на 95%.' },
98
+ { type: 'card', title: 'Почему WebP: это будущее', html: 'Google разработал WebP специально для веба. Он предлагает лучшее сжатие, чем JPEG и PNG, сохраняя или улучшая визуальное качество. Он на 25-35% меньше эквивалентов JPEG. Современные браузеры поддерживают его на 95%.' },
99
99
 
100
100
  { type: 'title', text: 'Сжатие с потерями и без потерь', level: 3 },
101
101
  { type: 'comparative', items: [
102
102
  {
103
103
  title: 'Сжатие с потерями (Lossy)',
104
- description: 'JPG, WebP удаляет незаметную визуальную информацию',
104
+ description: 'JPG, WebP - удаляет незаметную визуальную информацию',
105
105
  icon: 'mdi:compress',
106
106
  points: [
107
107
  'Уменьшает вес на 70-90% от исходного',
@@ -113,7 +113,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
113
113
  },
114
114
  {
115
115
  title: 'Сжатие без потерь (Lossless)',
116
- description: 'PNG, WebP без потерь сохраняет 100% визуальных данных',
116
+ description: 'PNG, WebP без потерь - сохраняет 100% визуальных данных',
117
117
  icon: 'mdi:shield',
118
118
  points: [
119
119
  'Уменьшает вес на 20-50%',
@@ -147,7 +147,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
147
147
  },
148
148
  {
149
149
  pro: 'Опциональное изменение размера: уменьшает как разрешение, так и сжатие',
150
- con: 'Изменение размера приводит к потере информации лучше оптимизировать разрешение в источнике'
150
+ con: 'Изменение размера приводит к потере информации - лучше оптимизировать разрешение в источнике'
151
151
  }
152
152
  ], proTitle: 'Преимущества', conTitle: 'Ограничения' },
153
153
 
@@ -156,7 +156,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
156
156
  { type: 'glossary', items: [
157
157
  {
158
158
  term: 'Сжатие с потерями (Lossy)',
159
- definition: 'Удаляет визуальные данные, которые человеческий глаз воспринимает как «шум». Идеально для фотографий. JPEG, WebP с потерями, HEIC являются форматами с потерями.'
159
+ definition: 'Удаляет визуальные данные, которые человеческий глаз воспринимает как \"шум\". Идеально для фотографий. JPEG, WebP с потерями, HEIC являются форматами с потерями.'
160
160
  },
161
161
  {
162
162
  term: 'Сжатие без потерь (Lossless)',
@@ -176,7 +176,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
176
176
  }
177
177
  ] },
178
178
 
179
- { type: 'message', title: 'Профессиональная веб оптимизация', ariaLabel: 'Информация об оптимизации изображений для SEO', html: 'Это не техническая прихоть: сжатие изображений это прямая инвестиция в пользовательский опыт и рейтинг в Google. На мобильных устройствах важен каждый килобайт. Наш инструмент превращает то, что раньше требовало профессионального ПО ($$$), в бесплатный процесс в 3 клика.' },
179
+ { type: 'message', title: 'Профессиональная веб оптимизация', ariaLabel: 'Информация об оптимизации изображений для SEO', html: 'Это не техническая прихоть: сжатие изображений - это прямая инвестиция в пользовательский опыт и рейтинг в Google. На мобильных устройствах важен каждый килобайт. Наш инструмент превращает то, что раньше требовало профессионального ПО ($$$), в бесплатный процесс в 3 клика.' },
180
180
 
181
181
  { type: 'title', text: 'Готовы к современному вебу', level: 3 },
182
182
  { type: 'paragraph', html: 'Используйте интеллектуальное сжатие и формат WebP, чтобы ваше онлайн-присутствие было быстрым, адаптивным и конкурентоспособным в поиске. Профессиональное качество, минимальный вес, мгновенная загрузка.' }
@@ -158,7 +158,7 @@ const seo: ImageCompressorLocaleContent['seo'] = [
158
158
  { type: 'glossary', items: [
159
159
  {
160
160
  term: '有损压缩',
161
- definition: '删除人眼视为“噪声”的视觉数据。摄影的理想选择。JPEG、有损 WebP、HEIC 均属于有损压缩。'
161
+ definition: '删除人眼视为\"噪声\"的视觉数据。摄影的理想选择。JPEG、有损 WebP、HEIC 均属于有损压缩。'
162
162
  },
163
163
  {
164
164
  term: '无损压缩',
@@ -10,126 +10,134 @@ const { ui } = Astro.props;
10
10
  ---
11
11
 
12
12
  <div class="pq-wrapper" id="pq-root" data-ui={JSON.stringify(ui)}>
13
- <div
14
- id="drop-zone"
15
- class="pq-drop-zone pq-group"
16
- >
17
- <input type="file" id="file-input" class="pq-hidden" accept="image/webp, image/jpeg, image/png, image/tiff" />
18
-
19
- <div class="pq-drop-inner">
20
- <div class="pq-upload-icon-wrap pq-group-icon">
21
- <Icon name="mdi:cloud-upload" style="width:2.5rem;height:2.5rem" />
22
- </div>
23
- <div>
24
- <h3 class="pq-drop-title">{ui.dropTitle}</h3>
25
- <p class="pq-drop-sub">{ui.dropSubtitle}</p>
13
+ <div class="pq-tool-card">
14
+ <div
15
+ id="drop-zone"
16
+ class="pq-drop-zone pq-group"
17
+ >
18
+ <input type="file" id="file-input" class="pq-hidden" accept="image/webp, image/jpeg, image/png, image/tiff" aria-label={ui.dropTitle} />
19
+
20
+ <div class="pq-drop-inner">
21
+ <div class="pq-upload-icon-wrap pq-group-icon">
22
+ <Icon name="mdi:cloud-upload" style="width:2.5rem;height:2.5rem" />
23
+ </div>
24
+ <div>
25
+ <h3 class="pq-drop-title">{ui.dropTitle}</h3>
26
+ <p class="pq-drop-sub">{ui.dropSubtitle}</p>
27
+ </div>
26
28
  </div>
27
- </div>
28
29
 
29
- <div class="pq-drop-overlay"></div>
30
- </div>
30
+ <div class="pq-drop-overlay"></div>
31
+ </div>
31
32
 
32
- <div id="results-area" class="pq-results pq-hidden">
33
- <div class="pq-file-card">
34
- <div class="pq-file-left">
35
- <div class="pq-preview-wrap">
36
- <img id="preview-img" class="pq-preview-img" src="#" alt="Preview" />
37
- </div>
38
- <div class="pq-file-info">
39
- <h3 id="file-name" class="pq-file-name">nombre_archivo.jpg</h3>
40
- <div class="pq-file-meta">
41
- <span class="pq-meta-item">
42
- <Icon name="mdi:arrow-expand" style="width:1rem;height:1rem" />
43
- <span id="pixel-dims">0 x 0 px</span>
44
- </span>
45
- <span class="pq-meta-item">
46
- <Icon name="mdi:harddisk" style="width:1rem;height:1rem" />
47
- <span id="file-size">0 MB</span>
48
- </span>
49
- <span class="pq-meta-item">
50
- <Icon name="mdi:image-filter-hdr" style="width:1rem;height:1rem" />
51
- <span id="megapixels">0 MP</span>
52
- </span>
33
+ <div id="results-area" class="pq-results pq-hidden">
34
+ <div class="pq-file-card">
35
+ <div class="pq-file-left">
36
+ <div class="pq-preview-wrap" id="preview-wrap">
37
+ <img id="preview-img" class="pq-preview-img" src="#" alt="Preview" />
38
+ </div>
39
+ <div class="pq-file-info">
40
+ <div class="pq-file-header">
41
+ <p id="file-name" class="pq-file-name">nombre_archivo.jpg</p>
42
+ <button type="button" id="replace-image-btn" class="pq-replace-btn">
43
+ <Icon name="mdi:image-refresh" style="width:1rem;height:1rem" />
44
+ <span>{ui.dropTitle}</span>
45
+ </button>
46
+ </div>
47
+ <div class="pq-file-meta">
48
+ <span class="pq-meta-item">
49
+ <Icon name="mdi:arrow-expand" style="width:1rem;height:1rem" />
50
+ <span id="pixel-dims">0 x 0 px</span>
51
+ </span>
52
+ <span class="pq-meta-item">
53
+ <Icon name="mdi:harddisk" style="width:1rem;height:1rem" />
54
+ <span id="file-size">0 MB</span>
55
+ </span>
56
+ <span class="pq-meta-item">
57
+ <Icon name="mdi:image-filter-hdr" style="width:1rem;height:1rem" />
58
+ <span id="megapixels">0 MP</span>
59
+ </span>
60
+ </div>
53
61
  </div>
54
62
  </div>
55
63
  </div>
56
- </div>
57
64
 
58
- <div class="pq-main-grid">
59
- <div class="pq-config-panel">
60
- <label class="pq-config-label">{ui.dpiDensityLabel}</label>
61
-
62
- <input
63
- type="range"
64
- id="dpi-slider"
65
- min="72"
66
- max="600"
67
- value="300"
68
- step="1"
69
- class="pq-slider"
70
- />
71
-
72
- <div class="pq-dpi-row">
65
+ <div class="pq-main-grid">
66
+ <div class="pq-config-panel">
67
+ <label class="pq-config-label" for="dpi-slider">{ui.dpiDensityLabel}</label>
68
+
73
69
  <input
74
- type="number"
75
- id="dpi-input"
70
+ type="range"
71
+ id="dpi-slider"
72
+ min="72"
73
+ max="600"
76
74
  value="300"
77
- class="pq-dpi-number"
75
+ step="1"
76
+ class="pq-slider"
78
77
  />
79
- <span class="pq-dpi-label">{ui.dpiPointsLabel}</span>
80
- </div>
81
78
 
82
- <div class="pq-presets">
83
- <button class="pq-preset-btn" data-val="72">{ui.dpiScreenLabel} (72)</button>
84
- <button class="pq-preset-btn" data-val="150">{ui.dpiNewspaperLabel} (150)</button>
85
- <button class="pq-preset-btn pq-preset-active" data-val="300">{ui.dpiPrintLabel} (300)</button>
86
- <button class="pq-preset-btn" data-val="600">{ui.dpiFineArtLabel} (600)</button>
87
- </div>
88
- </div>
89
-
90
- <div class="pq-output-panel">
91
- <div class="pq-output-gradient">
92
- <div class="pq-output-blur-bg"></div>
93
- <h3 class="pq-output-subtitle">{ui.maxPrintTitle}</h3>
94
-
95
- <div class="pq-output-size">
96
- <span id="print-cm-w">0</span>
97
- <span class="pq-size-sep">x</span>
98
- <span id="print-cm-h">0</span>
99
- <span class="pq-size-unit">cm</span>
79
+ <div class="pq-dpi-row">
80
+ <input
81
+ type="number"
82
+ id="dpi-input"
83
+ value="300"
84
+ class="pq-dpi-number"
85
+ />
86
+ <label class="pq-dpi-label" for="dpi-input">{ui.dpiPointsLabel}</label>
100
87
  </div>
101
88
 
102
- <div class="pq-output-inches">
103
- <span id="print-in-w">0</span>" x <span id="print-in-h">0</span>"
89
+ <div class="pq-presets">
90
+ <button class="pq-preset-btn" data-val="72">{ui.dpiScreenLabel} (72)</button>
91
+ <button class="pq-preset-btn" data-val="150">{ui.dpiNewspaperLabel} (150)</button>
92
+ <button class="pq-preset-btn pq-preset-active" data-val="300">{ui.dpiPrintLabel} (300)</button>
93
+ <button class="pq-preset-btn" data-val="600">{ui.dpiFineArtLabel} (600)</button>
104
94
  </div>
95
+ </div>
105
96
 
106
- <div class="pq-quality-section">
107
- <span id="quality-badge" class="pq-quality-badge">
108
- <Icon name="mdi:check-decagram" style="width:1rem;height:1rem" />
109
- <span id="quality-text">{ui.qualityExcellent}</span>
110
- </span>
111
- <p id="quality-desc" class="pq-quality-desc">{ui.qualityExcellentDesc}</p>
97
+ <div class="pq-output-panel">
98
+ <div class="pq-output-gradient">
99
+ <div class="pq-output-blur-bg"></div>
100
+ <h3 class="pq-output-subtitle">{ui.maxPrintTitle}</h3>
101
+
102
+ <div class="pq-output-size">
103
+ <span id="print-cm-w">0</span>
104
+ <span class="pq-size-sep">x</span>
105
+ <span id="print-cm-h">0</span>
106
+ <span class="pq-size-unit">cm</span>
107
+ </div>
108
+
109
+ <div class="pq-output-inches">
110
+ <span id="print-in-w">0</span>" x <span id="print-in-h">0</span>"
111
+ </div>
112
+
113
+ <div class="pq-quality-section">
114
+ <span id="quality-badge" class="pq-quality-badge">
115
+ <Icon name="mdi:check-decagram" style="width:1rem;height:1rem" />
116
+ <span id="quality-text">{ui.qualityExcellent}</span>
117
+ </span>
118
+ <p id="quality-desc" class="pq-quality-desc">{ui.qualityExcellentDesc}</p>
119
+ </div>
112
120
  </div>
113
121
  </div>
114
122
  </div>
115
- </div>
116
123
 
117
- <div class="pq-formats-card">
118
- <h4 class="pq-formats-title">
119
- <Icon name="mdi:ruler-square" style="width:1.2rem;height:1.2rem;color:#6366f1" />
120
- {ui.standardFormatsTitle}
121
- </h4>
122
- <div class="pq-formats-scroll">
123
- <table class="pq-formats-table">
124
- <thead>
125
- <tr>
126
- <th>{ui.formatColumn}</th>
127
- <th>{ui.measureColumn} (cm)</th>
128
- <th>{ui.supportColumn}</th>
129
- </tr>
130
- </thead>
131
- <tbody id="formats-table-body"></tbody>
132
- </table>
124
+ <div class="pq-formats-card">
125
+ <h4 class="pq-formats-title">
126
+ <Icon name="mdi:ruler-square" style="width:1.2rem;height:1.2rem;color:#6366f1" />
127
+ {ui.standardFormatsTitle}
128
+ </h4>
129
+ <div class="pq-formats-scroll">
130
+ <table class="pq-formats-table">
131
+ <thead>
132
+ <tr>
133
+ <th>{ui.formatColumn}</th>
134
+ <th>{ui.measureColumn} (cm)</th>
135
+ <th>{ui.supportColumn}</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody id="formats-table-body"></tbody>
139
+ </table>
140
+ </div>
133
141
  </div>
134
142
  </div>
135
143
  </div>
@@ -150,10 +158,6 @@ const { ui } = Astro.props;
150
158
  ];
151
159
 
152
160
  function initPQCalc() {
153
- console.log('DEBUG: initPQCalc called');
154
- console.log('DEBUG: ui object:', ui);
155
- console.log('DEBUG: ui.formatPostal:', ui.formatPostal);
156
-
157
161
  function getFormatName(format) {
158
162
  const keyMap = {
159
163
  postal: 'formatPostal',
@@ -165,9 +169,7 @@ const { ui } = Astro.props;
165
169
  plane: 'formatPlane'
166
170
  };
167
171
  const uiKey = keyMap[format.key];
168
- const result = format.label + ' (' + (ui[uiKey] || format.key) + ')';
169
- console.log('DEBUG: getFormatName for', format.key, '=', result, '(uiKey:', uiKey, ', ui[uiKey]:', ui[uiKey], ')');
170
- return result;
172
+ return format.label + ' (' + (ui[uiKey] || format.key) + ')';
171
173
  }
172
174
 
173
175
  const dropZone = document.getElementById("drop-zone");
@@ -176,6 +178,8 @@ const { ui } = Astro.props;
176
178
  if (!dropZone || !fileInput || !resultsArea) return;
177
179
 
178
180
  const previewImg = document.getElementById("preview-img");
181
+ const previewWrap = document.getElementById("preview-wrap");
182
+ const replaceImageBtn = document.getElementById("replace-image-btn");
179
183
  const fileNameEl = document.getElementById("file-name");
180
184
  const pixelDimsEl = document.getElementById("pixel-dims");
181
185
  const fileSizeEl = document.getElementById("file-size");
@@ -212,6 +216,11 @@ const { ui } = Astro.props;
212
216
  });
213
217
 
214
218
  dropZone.addEventListener("click", function() { fileInput.click(); });
219
+ if (replaceImageBtn) {
220
+ replaceImageBtn.addEventListener("click", function() {
221
+ fileInput.click();
222
+ });
223
+ }
215
224
 
216
225
  fileInput.addEventListener("change", function() {
217
226
  if (fileInput.files && fileInput.files.length > 0) processFile(fileInput.files[0]);
@@ -251,6 +260,7 @@ const { ui } = Astro.props;
251
260
  resultsArea.classList.remove("pq-hidden");
252
261
  dropZone.classList.add("pq-hidden");
253
262
  if (previewImg) previewImg.src = src;
263
+ if (previewWrap) previewWrap.classList.toggle("pq-hidden", !src);
254
264
  if (fileNameEl) fileNameEl.textContent = file.name;
255
265
  if (pixelDimsEl) pixelDimsEl.textContent = currentWidth + " x " + currentHeight + " px";
256
266
  if (fileSizeEl) fileSizeEl.textContent = (file.size / (1024 * 1024)).toFixed(2) + " MB";
@@ -311,13 +321,11 @@ const { ui } = Astro.props;
311
321
  }
312
322
 
313
323
  function updateFormatsTable(cmW, cmH) {
314
- console.log('DEBUG: updateFormatsTable called, ui.supportedText:', ui.supportedText);
315
324
  if (!formatsTableBody) return;
316
325
  formatsTableBody.innerHTML = "";
317
326
  const imgMin = Math.min(cmW, cmH);
318
327
  const imgMax = Math.max(cmW, cmH);
319
328
  PAPER_FORMATS.forEach(function(paper) {
320
- console.log('DEBUG: Processing paper format:', paper.key);
321
329
  const paperMin = Math.min(paper.w, paper.h);
322
330
  const paperMax = Math.max(paper.w, paper.h);
323
331
  const covers = imgMin >= paperMin - 0.1 && imgMax >= paperMax - 0.1;
@@ -54,7 +54,7 @@ const faq: PrintQualityCalculatorLocaleContent['faq'] = [
54
54
  },
55
55
  {
56
56
  question: "Kann ich die DPI meines Bildes erhöhen, ohne an Qualität zu verlieren?",
57
- answer: "Nein. Erhöhen Sie die DPI, ohne die Pixel zu ändern, verringert sich einfach die Druckgröße. Wenn Sie Pixel mit Software erfinden (Upscaling), kann das Bild unscharf wirken.",
57
+ answer: "Nein. Erhöhen Sie die DPI, ohne die Pixel zu ändern, verringert sich einfach die Druckgröße. Wenn Sie Pixel mit Software \"erfinden\" (Upscaling), kann das Bild unscharf wirken.",
58
58
  },
59
59
  ];
60
60
 
@@ -73,7 +73,7 @@ const howTo: PrintQualityCalculatorLocaleContent['howTo'] = [
73
73
  },
74
74
  {
75
75
  name: "Qualität bestätigen",
76
- text: "Stellen Sie sicher, dass die Anzeige Hervorragende Qualität anzeigt, bevor Sie den Druck in Auftrag geben.",
76
+ text: "Stellen Sie sicher, dass die Anzeige \"Hervorragende Qualität\" anzeigt, bevor Sie den Druck in Auftrag geben.",
77
77
  },
78
78
  ];
79
79
 
@@ -154,7 +154,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
154
154
  { type: 'proscons', items: [
155
155
  {
156
156
  pro: 'CMYK vs. RGB: Drucker verwenden Tinte (CMYK), Bildschirme Licht (RGB). Konvertieren Sie, um Farbüberraschungen zu vermeiden.',
157
- con: 'Farben können sich beim Konvertieren ändern erst Vorschau prüfen'
157
+ con: 'Farben können sich beim Konvertieren ändern - erst Vorschau prüfen'
158
158
  },
159
159
  {
160
160
  pro: 'Beschnitt: Fügen Sie 3 mm extra pro Seite hinzu, wenn das Bild bis zum Papierrand reichen soll',
@@ -170,7 +170,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
170
170
  }
171
171
  ], proTitle: 'Empfehlungen', conTitle: 'Gegenanzeigen' },
172
172
 
173
- { type: 'diagnostic', variant: 'warning', title: 'Häufiger Fehler: Der Upscaling Mythos', icon: 'mdi:alert', badge: 'Kritisch', html: '<strong>Erhöhen Sie DPI in Photoshop NICHT ohne die Pixel zu ändern.</strong> Eine Erhöhung von 72 DPI auf 300 DPI verringert einfach die physische Druckgröße. Wenn Sie Pixel durch Interpolation (Upscaling) hinzufügen“, wirkt das Bild geglättet oder unscharf. Sie benötigen REAL-Pixel von der Quelle.' },
173
+ { type: 'diagnostic', variant: 'warning', title: 'Häufiger Fehler: Der Upscaling Mythos', icon: 'mdi:alert', badge: 'Kritisch', html: '<strong>Erhöhen Sie DPI in Photoshop NICHT ohne die Pixel zu ändern.</strong> Eine Erhöhung von 72 DPI auf 300 DPI verringert einfach die physische Druckgröße. Wenn Sie Pixel durch Interpolation (Upscaling) \"hinzufügen\", wirkt das Bild geglättet oder unscharf. Sie benötigen REAL-Pixel von der Quelle.' },
174
174
 
175
175
  { type: 'glossary', items: [
176
176
  {
@@ -187,7 +187,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
187
187
  },
188
188
  {
189
189
  term: 'Native Auflösung',
190
- definition: 'ECHTE, von der Kamera erfasste Pixel ohne Manipulation. DPI-Erhöhung ohne Pixeländerung erzeugt keine native Auflösung“.'
190
+ definition: 'ECHTE, von der Kamera erfasste Pixel ohne Manipulation. DPI-Erhöhung ohne Pixeländerung erzeugt keine \"native Auflösung\".'
191
191
  },
192
192
  {
193
193
  term: 'Interpolation (Upscaling)',