@jjlmoya/utils-audiovisual 1.6.0 → 1.7.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.
- package/package.json +58 -58
- package/src/category/i18n/fr.ts +1 -1
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tool/chromaticLens/i18n/en.ts +1 -1
- package/src/tool/chromaticLens/i18n/es.ts +1 -1
- package/src/tool/chromaticLens/i18n/fr.ts +1 -1
- package/src/tool/collageMaker/i18n/en.ts +1 -1
- package/src/tool/collageMaker/i18n/es.ts +1 -1
- package/src/tool/collageMaker/i18n/fr.ts +1 -1
- package/src/tool/exifCleaner/i18n/en.ts +2 -2
- package/src/tool/exifCleaner/i18n/es.ts +2 -2
- package/src/tool/exifCleaner/i18n/fr.ts +3 -3
- package/src/tool/imageCompressor/i18n/en.ts +1 -1
- package/src/tool/imageCompressor/i18n/es.ts +1 -1
- package/src/tool/printQualityCalculator/i18n/en.ts +2 -2
- package/src/tool/printQualityCalculator/i18n/es.ts +3 -3
- package/src/tool/printQualityCalculator/i18n/fr.ts +2 -2
- package/src/tool/privacyBlur/i18n/en.ts +1 -1
- package/src/tool/privacyBlur/i18n/es.ts +1 -1
- package/src/tool/privacyBlur/i18n/fr.ts +1 -1
- package/src/tool/subtitleSync/i18n/en.ts +1 -1
- package/src/tool/subtitleSync/i18n/es.ts +1 -1
- package/src/tool/subtitleSync/i18n/fr.ts +3 -3
- package/src/tool/tvDistance/i18n/en.ts +1 -1
- package/src/tool/tvDistance/i18n/es.ts +1 -1
- package/src/tool/tvDistance/i18n/fr.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/en.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/es.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/fr.ts +1 -1
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
2
|
+
"name": "@jjlmoya/utils-audiovisual",
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.ts",
|
|
9
|
+
"./data": "./src/data.ts"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "astro dev",
|
|
19
|
+
"start": "astro dev",
|
|
20
|
+
"build": "astro build",
|
|
21
|
+
"preview": "astro preview",
|
|
22
|
+
"astro": "astro",
|
|
23
|
+
"lint": "eslint src/ --max-warnings 0 && stylelint \"src/**/*.{css,astro}\"",
|
|
24
|
+
"check": "astro check",
|
|
25
|
+
"type-check": "astro check",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"preversion": "npm run lint && npm run test",
|
|
28
|
+
"postversion": "git push && git push --tags",
|
|
29
|
+
"patch": "npm version patch",
|
|
30
|
+
"minor": "npm version minor",
|
|
31
|
+
"major": "npm version major"
|
|
32
|
+
},
|
|
33
|
+
"lint-staged": {
|
|
34
|
+
"*.{ts,tsx,astro}": [
|
|
35
|
+
"eslint --fix"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@iconify-json/mdi": "^1.2.3",
|
|
40
|
+
"@jjlmoya/utils-shared": "1.2.0",
|
|
41
|
+
"astro": "^6.1.2",
|
|
42
|
+
"astro-icon": "^1.1.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@astrojs/check": "^0.9.8",
|
|
46
|
+
"eslint": "^9.39.4",
|
|
47
|
+
"eslint-plugin-astro": "^1.6.0",
|
|
48
|
+
"eslint-plugin-no-comments": "^1.1.10",
|
|
49
|
+
"husky": "^9.1.7",
|
|
50
|
+
"lint-staged": "^16.4.0",
|
|
51
|
+
"postcss-html": "^1.8.1",
|
|
52
|
+
"schema-dts": "^1.1.2",
|
|
53
|
+
"stylelint": "^17.6.0",
|
|
54
|
+
"stylelint-config-standard": "^40.0.0",
|
|
55
|
+
"stylelint-declaration-strict-value": "^1.11.1",
|
|
56
|
+
"typescript": "^5.4.0",
|
|
57
|
+
"typescript-eslint": "^8.58.0",
|
|
58
|
+
"vitest": "^4.1.2"
|
|
59
|
+
}
|
|
60
60
|
}
|
package/src/category/i18n/fr.ts
CHANGED
|
@@ -74,7 +74,7 @@ export const content: CategoryLocaleContent = {
|
|
|
74
74
|
]
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
|
-
title: '
|
|
77
|
+
title: 'Synchronisation SRT',
|
|
78
78
|
description: 'Synchronisez, ajustez et éditez les sous-titres avec une précision à la milliseconde.',
|
|
79
79
|
icon: 'mdi:text',
|
|
80
80
|
points: [
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ALL_TOOLS } from '../tools';
|
|
3
|
+
import type { ToolLocaleContent } from '../types';
|
|
4
|
+
|
|
5
|
+
describe('Schemas Fulfillment Validation', () => {
|
|
6
|
+
ALL_TOOLS.forEach((tool) => {
|
|
7
|
+
describe(`Tool: ${tool.entry.id}`, () => {
|
|
8
|
+
Object.keys(tool.entry.i18n).forEach((locale) => {
|
|
9
|
+
it(`Locale: ${locale} should have faqSchema, appSchema and howToSchema`, async () => {
|
|
10
|
+
const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
|
|
11
|
+
if (!loader) return;
|
|
12
|
+
const content = (await loader()) as ToolLocaleContent;
|
|
13
|
+
|
|
14
|
+
const schemaTypes = content.schemas.map((s: any) => s['@type']);
|
|
15
|
+
|
|
16
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing FAQPage schema`).toContain('FAQPage');
|
|
17
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing SoftwareApplication schema`).toContain('SoftwareApplication');
|
|
18
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing HowTo schema`).toContain('HowTo');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
function getFiles(dir: string, ext: string[]): string[] {
|
|
6
|
+
const results: string[] = [];
|
|
7
|
+
if (!fs.existsSync(dir)) return results;
|
|
8
|
+
const list = fs.readdirSync(dir);
|
|
9
|
+
for (const file of list) {
|
|
10
|
+
const fullPath = path.join(dir, file);
|
|
11
|
+
const stat = fs.statSync(fullPath);
|
|
12
|
+
if (stat && stat.isDirectory()) {
|
|
13
|
+
results.push(...getFiles(fullPath, ext));
|
|
14
|
+
} else if (ext.some((e) => file.endsWith(e))) {
|
|
15
|
+
results.push(fullPath);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return results;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const SRC_DIR = path.join(process.cwd(), 'src');
|
|
22
|
+
|
|
23
|
+
describe('Project Titles - Separator Validation', () => {
|
|
24
|
+
const files = [
|
|
25
|
+
...getFiles(path.join(SRC_DIR, 'tool'), ['.ts']),
|
|
26
|
+
...getFiles(path.join(SRC_DIR, 'category'), ['.ts']),
|
|
27
|
+
].filter(f => f.includes('i18n'));
|
|
28
|
+
|
|
29
|
+
it.each(files)('Verify that titles in %s do not contain | or -', (filePath) => {
|
|
30
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
31
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
32
|
+
|
|
33
|
+
const titlePatterns = [
|
|
34
|
+
/const\s+title\s*=\s*['"]([^'"]+)['"]/g,
|
|
35
|
+
/title\s*:\s*['"]([^'"]+)['"]/g,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const findings: string[] = [];
|
|
39
|
+
|
|
40
|
+
for (const pattern of titlePatterns) {
|
|
41
|
+
let match;
|
|
42
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
43
|
+
const title = match[1];
|
|
44
|
+
if (title.includes('|') || title.includes('-')) {
|
|
45
|
+
findings.push(title);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (findings.length > 0) {
|
|
51
|
+
const list = findings.map((f) => ` - "${f}"`).join('\n');
|
|
52
|
+
throw new Error(`Forbidden separators (| or -) found in titles in ${relativePath}:\n${list}`);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'chromatic-lens-color-palette-extraction-online';
|
|
5
|
-
const title = 'Chromatic Lens
|
|
5
|
+
const title = 'Chromatic Lens: Online Color Palette Extraction';
|
|
6
6
|
const description = 'Extract professional color palettes from any image for free. Identify dominant colors in your photos using mathematical algorithms.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'lente-cromatica';
|
|
5
|
-
const title = 'Lente Cromática
|
|
5
|
+
const title = 'Lente Cromática: Extracción de Paletas de Color Online';
|
|
6
6
|
const description = 'Extrae paletas de colores profesionales de cualquier imagen de forma gratuita. Identifica los colores dominantes de tus fotos mediante algoritmos matemáticos.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'lentille-chromatique-extraction-palette-couleurs-ligne';
|
|
5
|
-
const title = 'Lentille Chromatique
|
|
5
|
+
const title = 'Lentille Chromatique: Extraction de Palette de Couleurs en Ligne';
|
|
6
6
|
const description = 'Extrayez gratuitement des palettes de couleurs professionnelles à partir de n\'importe quelle image. Identifiez les couleurs dominantes à l\'aide d\'algorithmes mathématiques.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { CollageMakerUI, CollageMakerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'free-online-photo-collage-maker-professional-compositions';
|
|
5
|
-
const title = 'Online Collage Maker
|
|
5
|
+
const title = 'Online Collage Maker: Design professional compositions';
|
|
6
6
|
const description = 'Create photo collages for free in seconds. Choose from multiple layouts, adjust borders, and download in high quality without watermarks.';
|
|
7
7
|
|
|
8
8
|
const ui: CollageMakerUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { CollageMakerUI, CollageMakerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'creador-collage-fotos';
|
|
5
|
-
const title = 'Creador de Collages Online
|
|
5
|
+
const title = 'Creador de Collages Online: Diseña composiciones profesionales';
|
|
6
6
|
const description = 'Crea collages de fotos gratis en segundos. Elige entre múltiples diseños, ajusta bordes y descarga en alta calidad sin marcas de agua.';
|
|
7
7
|
|
|
8
8
|
const ui: CollageMakerUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { CollageMakerUI, CollageMakerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'createur-collage-photos-gratuit-compositions-professionnelles';
|
|
5
|
-
const title = 'Créateur de Collages en Ligne
|
|
5
|
+
const title = 'Créateur de Collages en Ligne: Concevez des compositions professionnelles';
|
|
6
6
|
const description = 'Créez des collages de photos gratuitement en quelques secondes. Choisissez parmi plusieurs mises en page, ajustez les bordures et téléchargez en haute qualité sans filigrane.';
|
|
7
7
|
|
|
8
8
|
const ui: CollageMakerUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ExifCleanerUI, ExifCleanerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'exif-metadata-cleaner-remove-gps-photo-privacy';
|
|
5
|
-
const title = 'EXIF Metadata Cleaner
|
|
5
|
+
const title = 'EXIF Metadata Cleaner: Remove GPS and Hidden Data from Photos';
|
|
6
6
|
const description = 'Free online tool to erase EXIF metadata, GPS coordinates, and camera specs from your images before sharing. 100% private: works without uploading photos to the internet.';
|
|
7
7
|
|
|
8
8
|
const ui: ExifCleanerUI = {
|
|
@@ -81,7 +81,7 @@ const bibliography: ExifCleanerLocaleContent['bibliography'] = [
|
|
|
81
81
|
const seo: ExifCleanerLocaleContent['seo'] = [
|
|
82
82
|
{
|
|
83
83
|
type: 'summary',
|
|
84
|
-
title: 'EXIF Metadata Cleaner
|
|
84
|
+
title: 'EXIF Metadata Cleaner: Protect Your Privacy',
|
|
85
85
|
items: [
|
|
86
86
|
'Remove GPS coordinates and location from your photos instantly',
|
|
87
87
|
'Erase camera model, serial number, and technical information',
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ExifCleanerUI, ExifCleanerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'limpiador-exif';
|
|
5
|
-
const title = 'Limpiador de Metadatos EXIF
|
|
5
|
+
const title = 'Limpiador de Metadatos EXIF: Elimina GPS y Datos Ocultos de Fotos';
|
|
6
6
|
const description = 'Herramienta online gratuita para borrar metadatos EXIF, coordenadas GPS y datos de cámara de tus imágenes antes de compartirlas. Privacidad total: funciona sin subir fotos a internet.';
|
|
7
7
|
|
|
8
8
|
const ui: ExifCleanerUI = {
|
|
@@ -81,7 +81,7 @@ const bibliography: ExifCleanerLocaleContent['bibliography'] = [
|
|
|
81
81
|
const seo: ExifCleanerLocaleContent['seo'] = [
|
|
82
82
|
{
|
|
83
83
|
type: 'summary',
|
|
84
|
-
title: 'Limpiador de Metadatos EXIF
|
|
84
|
+
title: 'Limpiador de Metadatos EXIF: Protege tu Privacidad',
|
|
85
85
|
items: [
|
|
86
86
|
'Elimina coordenadas GPS y ubicación de tus fotos al instante',
|
|
87
87
|
'Borra datos de modelo de cámara, número de serie e información técnica',
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ExifCleanerUI, ExifCleanerLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'nettoyeur-metadonnees-exif-supprimer-gps-confidentialite-photo';
|
|
5
|
-
const title = 'Nettoyeur de Métadonnées EXIF
|
|
5
|
+
const title = 'Nettoyeur de Métadonnées EXIF: Supprimez le GPS et les Données Cachées';
|
|
6
6
|
const description = 'Outil en ligne gratuit pour effacer les métadonnées EXIF, les coordonnées GPS et les caractéristiques de l\'appareil de vos images avant de les partager. 100 % confidentiel : fonctionne sans téléversement.';
|
|
7
7
|
|
|
8
8
|
const ui: ExifCleanerUI = {
|
|
@@ -81,7 +81,7 @@ const bibliography: ExifCleanerLocaleContent['bibliography'] = [
|
|
|
81
81
|
const seo: ExifCleanerLocaleContent['seo'] = [
|
|
82
82
|
{
|
|
83
83
|
type: 'summary',
|
|
84
|
-
title: 'Nettoyeur de Métadonnées EXIF
|
|
84
|
+
title: 'Nettoyeur de Métadonnées EXIF: Protégez votre Vie Privée',
|
|
85
85
|
items: [
|
|
86
86
|
'Supprimez instantanément les coordonnées GPS et la localisation de vos photos',
|
|
87
87
|
'Effacez le modèle de l\'appareil, le numéro de série et les informations techniques',
|
|
@@ -194,7 +194,7 @@ const seo: ExifCleanerLocaleContent['seo'] = [
|
|
|
194
194
|
|
|
195
195
|
{ type: 'tip', title: 'Conseil de Sécurité Numérique', html: '<strong>Nettoyez vos photos AVANT de les publier</strong> sur n\'importe quel réseau social. Même si vous supprimez une publication, les métadonnées ont pu être indexées par des moteurs de recherche ou des archives. Mieux vaut prévenir que guérir. Prenez l\'habitude : <br><br><em>Photo → Nettoyer EXIF → Publier</em>' },
|
|
196
196
|
|
|
197
|
-
{ type: 'diagnostic', variant: 'warning', title: 'Risques Réels
|
|
197
|
+
{ type: 'diagnostic', variant: 'warning', title: 'Risques Réels sans Nettoyage', icon: 'mdi:alert-circle', badge: 'Sécurité Critique', html: '<strong>Cas documentés :</strong><br>- Parents publiant des photos d\'enfants - les prédateurs ont suivi le GPS<br>- Photographes voyageurs - maisons cambriolées pendant leur absence<br>- Influenceurs - lieux de résidence identifiés par des fans obsessifs<br><br>Ce n\'est pas de la paranoïa : c\'est une hygiène numérique de base en 2026.' },
|
|
198
198
|
|
|
199
199
|
{ type: 'glossary', items: [
|
|
200
200
|
{
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ImageCompressorUI, ImageCompressorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'online-image-compressor-reduce-file-size-no-quality-loss';
|
|
5
|
-
const title = 'Online Image Compressor
|
|
5
|
+
const title = 'Online Image Compressor: Reduce weight without losing quality';
|
|
6
6
|
const description = 'Optimize and compress your JPG, PNG, and WebP photos for free. Reduce file size to improve your web loading speed locally.';
|
|
7
7
|
|
|
8
8
|
const ui: ImageCompressorUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ImageCompressorUI, ImageCompressorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'compresor-imagenes';
|
|
5
|
-
const title = 'Compresor de Imágenes Online
|
|
5
|
+
const title = 'Compresor de Imágenes Online: Reduce el peso sin perder calidad';
|
|
6
6
|
const description = 'Optimiza y comprime tus fotos JPG, PNG y WebP de forma gratuita. Reduce el tamaño de archivo para mejorar la velocidad de carga de tu web de forma local.';
|
|
7
7
|
|
|
8
8
|
const ui: ImageCompressorUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { PrintQualityCalculatorUI, PrintQualityCalculatorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'print-quality-calculator-pixels-to-cm-dpi';
|
|
5
|
-
const title = 'Print Quality Calculator
|
|
5
|
+
const title = 'Print Quality Calculator: Pixels to CM and DPI';
|
|
6
6
|
const description = 'Calculate the maximum print size of your photos based on their resolution. Convert pixels to centimeters and inches to ensure professional printing.';
|
|
7
7
|
|
|
8
8
|
const ui: PrintQualityCalculatorUI = {
|
|
@@ -140,7 +140,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
|
|
|
140
140
|
]
|
|
141
141
|
},
|
|
142
142
|
{
|
|
143
|
-
title: 'Wall Poster
|
|
143
|
+
title: 'Wall Poster A3 (30x42 cm)',
|
|
144
144
|
description: '150 DPI enough - viewed at a distance',
|
|
145
145
|
icon: 'mdi:wall-fire',
|
|
146
146
|
points: [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { PrintQualityCalculatorUI, PrintQualityCalculatorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
|
-
const slug = 'calidad-impresion';
|
|
5
|
-
const title = 'Calculadora de Calidad de Impresión
|
|
4
|
+
const slug = 'calculadora-calidad-impresion';
|
|
5
|
+
const title = 'Calculadora de Calidad de Impresión: Píxeles a CM y DPI';
|
|
6
6
|
const description = 'Calcula el tamaño máximo de impresión de tus fotos según su resolución. Convierte píxeles a centímetros y pulgadas para asegurar una impresión profesional.';
|
|
7
7
|
|
|
8
8
|
const ui: PrintQualityCalculatorUI = {
|
|
@@ -138,7 +138,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
|
|
|
138
138
|
]
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
|
-
title: 'Póster de Pared
|
|
141
|
+
title: 'Póster de Pared A3 (30x42 cm)',
|
|
142
142
|
description: '150 DPI suficiente - se ve a distancia',
|
|
143
143
|
icon: 'mdi:wall-fire',
|
|
144
144
|
points: [
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { PrintQualityCalculatorUI, PrintQualityCalculatorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'calculatrice-qualite-impression-pixels-cm-dpi';
|
|
5
|
-
const title = 'Calculatrice de Qualité d\'Impression
|
|
5
|
+
const title = 'Calculatrice de Qualité d\'Impression: Pixels en CM et DPI';
|
|
6
6
|
const description = 'Calculez la taille d\'impression maximale de vos photos en fonction de leur résolution. Convertissez les pixels en centimètres et en pouces pour une impression professionnelle.';
|
|
7
7
|
|
|
8
8
|
const ui: PrintQualityCalculatorUI = {
|
|
@@ -138,7 +138,7 @@ const seo: PrintQualityCalculatorLocaleContent['seo'] = [
|
|
|
138
138
|
]
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
|
-
title: 'Poster Mural
|
|
141
|
+
title: 'Poster Mural A3 (30x42 cm)',
|
|
142
142
|
description: '150 DPI suffisant - se voit à distance',
|
|
143
143
|
icon: 'mdi:wall-fire',
|
|
144
144
|
points: [
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { PrivacyBlurUI, PrivacyBlurLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'online-privacy-editor-pixelate-blur-faces-photos';
|
|
5
|
-
const title = 'Online Privacy Editor
|
|
5
|
+
const title = 'Online Privacy Editor: Pixelate and hide faces in photos';
|
|
6
6
|
const description = 'Protect your identity by censoring sensitive areas of your photos. Pixelate faces, blur documents, or cover private information 100% locally.';
|
|
7
7
|
|
|
8
8
|
const ui: PrivacyBlurUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { PrivacyBlurUI, PrivacyBlurLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'editor-privacidad';
|
|
5
|
-
const title = 'Editor de Privacidad Online
|
|
5
|
+
const title = 'Editor de Privacidad Online: Pixela y oculta rostros en fotos';
|
|
6
6
|
const description = 'Protege tu identidad censurando áreas sensibles de tus fotos. Pixela rostros, desenfoca documentos o tapa información privada de forma 100% local.';
|
|
7
7
|
|
|
8
8
|
const ui: PrivacyBlurUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { PrivacyBlurUI, PrivacyBlurLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'editeur-confidentialite-en-ligne-pixeliser-flouter-visages';
|
|
5
|
-
const title = 'Éditeur de Confidentialité en Ligne
|
|
5
|
+
const title = 'Éditeur de Confidentialité en Ligne: Pixélisez et masquez les visages';
|
|
6
6
|
const description = 'Protégez votre identité en censurant les zones sensibles de vos photos. Pixélisez les visages, floutez les documents ou masquez les informations privées 100 % localement.';
|
|
7
7
|
|
|
8
8
|
const ui: PrivacyBlurUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { SubtitleSyncUI, SubtitleSyncLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'synchronize-srt-subtitles-online-adjust-timing-free';
|
|
5
|
-
const title = 'Synchronize SRT Subtitles Online
|
|
5
|
+
const title = 'Synchronize SRT Subtitles Online: Adjust Timing for Free';
|
|
6
6
|
const description = 'Online tool to advance or delay SRT subtitles. Correct timing offset easily and download the synchronized file instantly.';
|
|
7
7
|
|
|
8
8
|
const ui: SubtitleSyncUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { SubtitleSyncUI, SubtitleSyncLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'sincronizar-subtitulos';
|
|
5
|
-
const title = 'Sincronizar Subtítulos SRT Online
|
|
5
|
+
const title = 'Sincronizar Subtítulos SRT Online: Ajusta el Tiempo Gratis';
|
|
6
6
|
const description = 'Herramienta online para adelantar o retrasar subtítulos SRT. Corrige el desfase de tiempo de forma sencilla y descarga el archivo sincronizado al instante.';
|
|
7
7
|
|
|
8
8
|
const ui: SubtitleSyncUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { SubtitleSyncUI, SubtitleSyncLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'synchroniser-sous-titres-srt-en-ligne-ajuster-temps-gratuit';
|
|
5
|
-
const title = '
|
|
5
|
+
const title = 'Synchronisation SRT en Ligne: Ajustez le Temps Gratuitement';
|
|
6
6
|
const description = 'Outil en ligne pour avancer ou retarder les sous-titres SRT. Corrigez le décalage de temps simplement et téléchargez le fichier synchronisé instantanément.';
|
|
7
7
|
|
|
8
8
|
const ui: SubtitleSyncUI = {
|
|
@@ -73,7 +73,7 @@ const bibliography: SubtitleSyncLocaleContent['bibliography'] = [
|
|
|
73
73
|
const seo: SubtitleSyncLocaleContent['seo'] = [
|
|
74
74
|
{
|
|
75
75
|
type: 'summary',
|
|
76
|
-
title: 'Synchronisation
|
|
76
|
+
title: 'Synchronisation SRT Professionnelle',
|
|
77
77
|
items: [
|
|
78
78
|
'Correction instantanée des décalages audio-sous-titres',
|
|
79
79
|
'Supporte les fichiers SRT (SubRip) standards',
|
|
@@ -103,7 +103,7 @@ const seo: SubtitleSyncLocaleContent['seo'] = [
|
|
|
103
103
|
{ type: 'title', text: 'Cas d\'Utilisation Courants', level: 3 },
|
|
104
104
|
{ type: 'comparative', items: [
|
|
105
105
|
{
|
|
106
|
-
title: 'Traducteurs et
|
|
106
|
+
title: 'Traducteurs et Professionnels SRT',
|
|
107
107
|
description: 'Synchroniser des traductions après avoir travaillé avec plusieurs versions vidéo',
|
|
108
108
|
icon: 'mdi:translate',
|
|
109
109
|
points: [
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { TvDistanceUI, TvDistanceLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'tv-viewing-distance-calculator-thx-4k-optimal-screen';
|
|
5
|
-
const title = 'TV Distance Calculator
|
|
5
|
+
const title = 'TV Distance Calculator: THX and 4K Optimal Screen';
|
|
6
6
|
const description = 'Calculate the ideal distance to watch your television based on its size and resolution. Optimize your Home Cinema with THX and SMPTE standards.';
|
|
7
7
|
|
|
8
8
|
const ui: TvDistanceUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { TvDistanceUI, TvDistanceLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'distancia-tv';
|
|
5
|
-
const title = 'Calculadora de Distancia TV
|
|
5
|
+
const title = 'Calculadora de Distancia TV: Pantalla Óptima THX y 4K';
|
|
6
6
|
const description = 'Calcula la distancia ideal para ver tu televisor según su tamaño y resolución. Optimiza tu Home Cinema con los estándares THX y SMPTE.';
|
|
7
7
|
|
|
8
8
|
const ui: TvDistanceUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { TvDistanceUI, TvDistanceLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'calculatrice-distance-tv-ecran-optimal-thx-4k';
|
|
5
|
-
const title = 'Calculatrice de Distance TV
|
|
5
|
+
const title = 'Calculatrice de Distance TV: Écran Optimal THX et 4K';
|
|
6
6
|
const description = 'Calculez la distance idéale pour regarder votre téléviseur en fonction de sa taille et de sa résolution. Optimisez votre Home Cinéma avec les standards THX et SMPTE.';
|
|
7
7
|
|
|
8
8
|
const ui: TvDistanceUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { VideoFrameExtractorUI, VideoFrameExtractorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'online-video-frame-extractor-capture-hd-stills';
|
|
5
|
-
const title = 'Video Frame Extractor
|
|
5
|
+
const title = 'Video Frame Extractor: Capture HD stills';
|
|
6
6
|
const description = 'Extract individual images from your videos with frame-perfect precision. Capture perfect moments in HD locally and for free.';
|
|
7
7
|
|
|
8
8
|
const ui: VideoFrameExtractorUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { VideoFrameExtractorUI, VideoFrameExtractorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'extractor-frames-video';
|
|
5
|
-
const title = 'Extractor de Frames de Vídeo
|
|
5
|
+
const title = 'Extractor de Frames de Vídeo: Captura fotogramas en alta resolución';
|
|
6
6
|
const description = 'Extrae imágenes individuales de tus vídeos con precisión de frame. Captura momentos perfectos en HD de forma local y gratuita.';
|
|
7
7
|
|
|
8
8
|
const ui: VideoFrameExtractorUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { VideoFrameExtractorUI, VideoFrameExtractorLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'extracteur-frames-video-en-ligne-capturer-images-hd';
|
|
5
|
-
const title = 'Extracteur de Frames de Vidéo
|
|
5
|
+
const title = 'Extracteur de Frames de Vidéo: Capturez des images haute résolution';
|
|
6
6
|
const description = 'Extrayez des images individuelles de vos vidéos avec une précision à l\'image près. Capturez des moments parfaits en HD localement et gratuitement.';
|
|
7
7
|
|
|
8
8
|
const ui: VideoFrameExtractorUI = {
|