pabal-resource-mcp 1.5.4 → 1.5.5
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/dist/bin/mcp-server.js +102 -26
- package/package.json +1 -1
package/dist/bin/mcp-server.js
CHANGED
|
@@ -3432,6 +3432,87 @@ import { GoogleGenAI } from "@google/genai";
|
|
|
3432
3432
|
import fs10 from "fs";
|
|
3433
3433
|
import path10 from "path";
|
|
3434
3434
|
import sharp from "sharp";
|
|
3435
|
+
var GEMINI_ASPECT_RATIOS = {
|
|
3436
|
+
"1:1": { ratio: 1 / 1, width: 2048, height: 2048 },
|
|
3437
|
+
"2:3": { ratio: 2 / 3, width: 1696, height: 2528 },
|
|
3438
|
+
"3:2": { ratio: 3 / 2, width: 2528, height: 1696 },
|
|
3439
|
+
"3:4": { ratio: 3 / 4, width: 1792, height: 2400 },
|
|
3440
|
+
"4:3": { ratio: 4 / 3, width: 2400, height: 1792 },
|
|
3441
|
+
"4:5": { ratio: 4 / 5, width: 1856, height: 2304 },
|
|
3442
|
+
"5:4": { ratio: 5 / 4, width: 2304, height: 1856 },
|
|
3443
|
+
"9:16": { ratio: 9 / 16, width: 1536, height: 2752 },
|
|
3444
|
+
"16:9": { ratio: 16 / 9, width: 2752, height: 1536 },
|
|
3445
|
+
"21:9": { ratio: 21 / 9, width: 1584, height: 672 }
|
|
3446
|
+
};
|
|
3447
|
+
var DEVICE_ASPECT_RATIOS = {
|
|
3448
|
+
phone: "9:16",
|
|
3449
|
+
tablet: "3:4"
|
|
3450
|
+
};
|
|
3451
|
+
var GEMINI_SUPPORTED_LOCALES = {
|
|
3452
|
+
// English variants
|
|
3453
|
+
"en": "EN",
|
|
3454
|
+
"en-US": "EN",
|
|
3455
|
+
"en-GB": "EN",
|
|
3456
|
+
"en-AU": "EN",
|
|
3457
|
+
"en-CA": "EN",
|
|
3458
|
+
// Arabic
|
|
3459
|
+
"ar": "ar-EG",
|
|
3460
|
+
"ar-EG": "ar-EG",
|
|
3461
|
+
"ar-SA": "ar-EG",
|
|
3462
|
+
// German
|
|
3463
|
+
"de": "de-DE",
|
|
3464
|
+
"de-DE": "de-DE",
|
|
3465
|
+
// Spanish
|
|
3466
|
+
"es": "es-MX",
|
|
3467
|
+
"es-MX": "es-MX",
|
|
3468
|
+
"es-ES": "es-MX",
|
|
3469
|
+
"es-419": "es-MX",
|
|
3470
|
+
// French
|
|
3471
|
+
"fr": "fr-FR",
|
|
3472
|
+
"fr-FR": "fr-FR",
|
|
3473
|
+
"fr-CA": "fr-FR",
|
|
3474
|
+
// Hindi
|
|
3475
|
+
"hi": "hi-IN",
|
|
3476
|
+
"hi-IN": "hi-IN",
|
|
3477
|
+
// Indonesian
|
|
3478
|
+
"id": "id-ID",
|
|
3479
|
+
"id-ID": "id-ID",
|
|
3480
|
+
// Italian
|
|
3481
|
+
"it": "it-IT",
|
|
3482
|
+
"it-IT": "it-IT",
|
|
3483
|
+
// Japanese
|
|
3484
|
+
"ja": "ja-JP",
|
|
3485
|
+
"ja-JP": "ja-JP",
|
|
3486
|
+
// Korean
|
|
3487
|
+
"ko": "ko-KR",
|
|
3488
|
+
"ko-KR": "ko-KR",
|
|
3489
|
+
// Portuguese
|
|
3490
|
+
"pt": "pt-BR",
|
|
3491
|
+
"pt-BR": "pt-BR",
|
|
3492
|
+
"pt-PT": "pt-BR",
|
|
3493
|
+
// Russian
|
|
3494
|
+
"ru": "ru-RU",
|
|
3495
|
+
"ru-RU": "ru-RU",
|
|
3496
|
+
// Ukrainian
|
|
3497
|
+
"uk": "ua-UA",
|
|
3498
|
+
"uk-UA": "ua-UA",
|
|
3499
|
+
"ua-UA": "ua-UA",
|
|
3500
|
+
// Vietnamese
|
|
3501
|
+
"vi": "vi-VN",
|
|
3502
|
+
"vi-VN": "vi-VN",
|
|
3503
|
+
// Chinese
|
|
3504
|
+
"zh": "zh-CN",
|
|
3505
|
+
"zh-CN": "zh-CN",
|
|
3506
|
+
"zh-Hans": "zh-CN",
|
|
3507
|
+
"zh-TW": "zh-CN",
|
|
3508
|
+
"zh-Hant": "zh-CN"
|
|
3509
|
+
};
|
|
3510
|
+
function isGeminiSupportedLocale(locale) {
|
|
3511
|
+
return locale in GEMINI_SUPPORTED_LOCALES;
|
|
3512
|
+
}
|
|
3513
|
+
function getUnsupportedLocales(locales) {
|
|
3514
|
+
return locales.filter((locale) => !isGeminiSupportedLocale(locale));
|
|
3515
|
+
}
|
|
3435
3516
|
var LANGUAGE_NAMES = {
|
|
3436
3517
|
"en-US": "English (US)",
|
|
3437
3518
|
"en-GB": "English (UK)",
|
|
@@ -3507,29 +3588,15 @@ function readImageAsBase64(imagePath) {
|
|
|
3507
3588
|
}
|
|
3508
3589
|
return { data: base64, mimeType };
|
|
3509
3590
|
}
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
return {
|
|
3513
|
-
width: metadata.width || 1080,
|
|
3514
|
-
height: metadata.height || 1920
|
|
3515
|
-
};
|
|
3516
|
-
}
|
|
3517
|
-
function calculateAspectRatio(width, height) {
|
|
3518
|
-
const ratio = width / height;
|
|
3519
|
-
if (Math.abs(ratio - 1) < 0.1) return "1:1";
|
|
3520
|
-
if (Math.abs(ratio - 9 / 16) < 0.1) return "9:16";
|
|
3521
|
-
if (Math.abs(ratio - 16 / 9) < 0.1) return "16:9";
|
|
3522
|
-
if (Math.abs(ratio - 3 / 4) < 0.1) return "3:4";
|
|
3523
|
-
if (Math.abs(ratio - 4 / 3) < 0.1) return "4:3";
|
|
3524
|
-
return ratio < 1 ? "9:16" : "16:9";
|
|
3591
|
+
function getAspectRatioForDevice(deviceType) {
|
|
3592
|
+
return DEVICE_ASPECT_RATIOS[deviceType];
|
|
3525
3593
|
}
|
|
3526
|
-
async function translateImage(sourcePath, sourceLocale, targetLocale, outputPath, preserveWords) {
|
|
3594
|
+
async function translateImage(sourcePath, sourceLocale, targetLocale, outputPath, deviceType, preserveWords) {
|
|
3527
3595
|
try {
|
|
3528
3596
|
const client = getGeminiClient();
|
|
3529
3597
|
const sourceLanguage = getLanguageName(sourceLocale);
|
|
3530
3598
|
const targetLanguage = getLanguageName(targetLocale);
|
|
3531
|
-
const
|
|
3532
|
-
const aspectRatio = calculateAspectRatio(width, height);
|
|
3599
|
+
const aspectRatio = getAspectRatioForDevice(deviceType);
|
|
3533
3600
|
const { data: imageData, mimeType } = readImageAsBase64(sourcePath);
|
|
3534
3601
|
const preserveInstruction = preserveWords && preserveWords.length > 0 ? `
|
|
3535
3602
|
- Do NOT translate these words, keep them exactly as-is: ${preserveWords.join(", ")}` : "";
|
|
@@ -3629,6 +3696,7 @@ async function translateImagesWithProgress(translations, onProgress, preserveWor
|
|
|
3629
3696
|
translation.sourceLocale,
|
|
3630
3697
|
translation.targetLocale,
|
|
3631
3698
|
translation.outputPath,
|
|
3699
|
+
translation.deviceType,
|
|
3632
3700
|
preserveWords
|
|
3633
3701
|
);
|
|
3634
3702
|
if (result.success) {
|
|
@@ -3652,7 +3720,7 @@ async function translateImagesWithProgress(translations, onProgress, preserveWor
|
|
|
3652
3720
|
// src/tools/aso/utils/localize-screenshots/image-resizer.util.ts
|
|
3653
3721
|
import sharp2 from "sharp";
|
|
3654
3722
|
import fs11 from "fs";
|
|
3655
|
-
async function
|
|
3723
|
+
async function getImageDimensions(imagePath) {
|
|
3656
3724
|
const metadata = await sharp2(imagePath).metadata();
|
|
3657
3725
|
if (!metadata.width || !metadata.height) {
|
|
3658
3726
|
throw new Error(`Unable to read dimensions from ${imagePath}`);
|
|
@@ -3723,14 +3791,16 @@ async function resizeImage(inputPath, outputPath, targetDimensions) {
|
|
|
3723
3791
|
// Preserve aspect ratio
|
|
3724
3792
|
withoutEnlargement: false,
|
|
3725
3793
|
// Allow enlargement if needed
|
|
3726
|
-
background: bgColor
|
|
3794
|
+
background: bgColor,
|
|
3727
3795
|
// Use detected edge color
|
|
3796
|
+
kernel: "lanczos3"
|
|
3797
|
+
// High-quality downscaling algorithm
|
|
3728
3798
|
}).flatten({ background: bgColor }).png().toFile(outputPath + ".tmp");
|
|
3729
3799
|
fs11.renameSync(outputPath + ".tmp", outputPath);
|
|
3730
3800
|
}
|
|
3731
3801
|
async function validateAndResizeImage(sourcePath, translatedPath) {
|
|
3732
|
-
const sourceDimensions = await
|
|
3733
|
-
const translatedDimensions = await
|
|
3802
|
+
const sourceDimensions = await getImageDimensions(sourcePath);
|
|
3803
|
+
const translatedDimensions = await getImageDimensions(translatedPath);
|
|
3734
3804
|
const needsResize = sourceDimensions.width !== translatedDimensions.width || sourceDimensions.height !== translatedDimensions.height;
|
|
3735
3805
|
if (needsResize) {
|
|
3736
3806
|
await resizeImage(translatedPath, translatedPath, sourceDimensions);
|
|
@@ -3865,12 +3935,14 @@ function getTargetLocales(allLocales, primaryLocale, requestedTargets) {
|
|
|
3865
3935
|
);
|
|
3866
3936
|
if (invalidTargets.length > 0) {
|
|
3867
3937
|
console.warn(
|
|
3868
|
-
`Warning: Some requested locales are not
|
|
3938
|
+
`Warning: Some requested locales are not in product: ${invalidTargets.join(", ")}`
|
|
3869
3939
|
);
|
|
3870
3940
|
}
|
|
3871
3941
|
targets = validTargets.filter((t) => t !== primaryLocale);
|
|
3872
3942
|
}
|
|
3873
|
-
|
|
3943
|
+
const skippedLocales = getUnsupportedLocales(targets);
|
|
3944
|
+
const supportedTargets = targets.filter((t) => isGeminiSupportedLocale(t));
|
|
3945
|
+
return { targets: supportedTargets, skippedLocales };
|
|
3874
3946
|
}
|
|
3875
3947
|
function buildTranslationTasks(slug, screenshots, primaryLocale, targetLocales, skipExisting) {
|
|
3876
3948
|
const tasks = [];
|
|
@@ -3941,22 +4013,26 @@ async function handleLocalizeScreenshots(input) {
|
|
|
3941
4013
|
]
|
|
3942
4014
|
};
|
|
3943
4015
|
}
|
|
3944
|
-
const targetLocales = getTargetLocales(
|
|
4016
|
+
const { targets: targetLocales, skippedLocales } = getTargetLocales(
|
|
3945
4017
|
allLocales,
|
|
3946
4018
|
primaryLocale,
|
|
3947
4019
|
requestedTargetLocales
|
|
3948
4020
|
);
|
|
3949
4021
|
if (targetLocales.length === 0) {
|
|
4022
|
+
const skippedMsg = skippedLocales.length > 0 ? ` (Skipped due to Gemini limitation: ${skippedLocales.join(", ")})` : "";
|
|
3950
4023
|
return {
|
|
3951
4024
|
content: [
|
|
3952
4025
|
{
|
|
3953
4026
|
type: "text",
|
|
3954
|
-
text: `\u274C No target locales to translate to. Primary locale: ${primaryLocale}, Available: ${allLocales.join(", ")}`
|
|
4027
|
+
text: `\u274C No target locales to translate to. Primary locale: ${primaryLocale}, Available: ${allLocales.join(", ")}${skippedMsg}`
|
|
3955
4028
|
}
|
|
3956
4029
|
]
|
|
3957
4030
|
};
|
|
3958
4031
|
}
|
|
3959
4032
|
results.push(`\u{1F3AF} Target locales: ${targetLocales.join(", ")}`);
|
|
4033
|
+
if (skippedLocales.length > 0) {
|
|
4034
|
+
results.push(`\u26A0\uFE0F Skipped locales (not supported by Gemini): ${skippedLocales.join(", ")}`);
|
|
4035
|
+
}
|
|
3960
4036
|
const sourceScreenshots = scanLocaleScreenshots(appInfo.slug, primaryLocale);
|
|
3961
4037
|
let filteredScreenshots = sourceScreenshots.filter(
|
|
3962
4038
|
(s) => deviceTypes.includes(s.type)
|