pabal-resource-mcp 1.5.5 → 1.5.6
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 +160 -149
- package/package.json +1 -1
package/dist/bin/mcp-server.js
CHANGED
|
@@ -3448,127 +3448,26 @@ var DEVICE_ASPECT_RATIOS = {
|
|
|
3448
3448
|
phone: "9:16",
|
|
3449
3449
|
tablet: "3:4"
|
|
3450
3450
|
};
|
|
3451
|
-
var
|
|
3452
|
-
|
|
3453
|
-
"
|
|
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
|
-
}
|
|
3516
|
-
var LANGUAGE_NAMES = {
|
|
3517
|
-
"en-US": "English (US)",
|
|
3518
|
-
"en-GB": "English (UK)",
|
|
3519
|
-
"en-AU": "English (Australia)",
|
|
3520
|
-
"en-CA": "English (Canada)",
|
|
3521
|
-
"ko-KR": "Korean",
|
|
3522
|
-
"ja-JP": "Japanese",
|
|
3523
|
-
"zh-Hans": "Simplified Chinese",
|
|
3524
|
-
"zh-Hant": "Traditional Chinese",
|
|
3525
|
-
"zh-CN": "Simplified Chinese",
|
|
3526
|
-
"zh-TW": "Traditional Chinese",
|
|
3527
|
-
"fr-FR": "French",
|
|
3528
|
-
"fr-CA": "French (Canada)",
|
|
3451
|
+
var GEMINI_LANGUAGE_NAMES = {
|
|
3452
|
+
"en-US": "English",
|
|
3453
|
+
"ar-EG": "Arabic",
|
|
3529
3454
|
"de-DE": "German",
|
|
3530
|
-
"es-
|
|
3531
|
-
"
|
|
3532
|
-
"
|
|
3533
|
-
"
|
|
3534
|
-
"pt-PT": "Portuguese (Portugal)",
|
|
3455
|
+
"es-MX": "Spanish",
|
|
3456
|
+
"fr-FR": "French",
|
|
3457
|
+
"hi-IN": "Hindi",
|
|
3458
|
+
"id-ID": "Indonesian",
|
|
3535
3459
|
"it-IT": "Italian",
|
|
3536
|
-
"
|
|
3460
|
+
"ja-JP": "Japanese",
|
|
3461
|
+
"ko-KR": "Korean",
|
|
3462
|
+
"pt-BR": "Portuguese",
|
|
3537
3463
|
"ru-RU": "Russian",
|
|
3538
|
-
"
|
|
3539
|
-
"ar-SA": "Arabic",
|
|
3540
|
-
"hi-IN": "Hindi",
|
|
3541
|
-
"th-TH": "Thai",
|
|
3464
|
+
"ua-UA": "Ukrainian",
|
|
3542
3465
|
"vi-VN": "Vietnamese",
|
|
3543
|
-
"
|
|
3544
|
-
"ms-MY": "Malay",
|
|
3545
|
-
"tr-TR": "Turkish",
|
|
3546
|
-
"pl-PL": "Polish",
|
|
3547
|
-
"uk-UA": "Ukrainian",
|
|
3548
|
-
"cs-CZ": "Czech",
|
|
3549
|
-
"el-GR": "Greek",
|
|
3550
|
-
"ro-RO": "Romanian",
|
|
3551
|
-
"hu-HU": "Hungarian",
|
|
3552
|
-
"sv-SE": "Swedish",
|
|
3553
|
-
"da-DK": "Danish",
|
|
3554
|
-
"fi-FI": "Finnish",
|
|
3555
|
-
"no-NO": "Norwegian",
|
|
3556
|
-
"he-IL": "Hebrew",
|
|
3557
|
-
"sk-SK": "Slovak",
|
|
3558
|
-
"bg-BG": "Bulgarian",
|
|
3559
|
-
"hr-HR": "Croatian",
|
|
3560
|
-
"ca-ES": "Catalan"
|
|
3466
|
+
"zh-CN": "Chinese"
|
|
3561
3467
|
};
|
|
3562
3468
|
function getLanguageName(locale) {
|
|
3563
|
-
if (
|
|
3564
|
-
return
|
|
3565
|
-
}
|
|
3566
|
-
const baseCode = locale.split("-")[0];
|
|
3567
|
-
const matchingKey = Object.keys(LANGUAGE_NAMES).find(
|
|
3568
|
-
(key) => key.startsWith(baseCode + "-") || key === baseCode
|
|
3569
|
-
);
|
|
3570
|
-
if (matchingKey) {
|
|
3571
|
-
return LANGUAGE_NAMES[matchingKey];
|
|
3469
|
+
if (locale in GEMINI_LANGUAGE_NAMES) {
|
|
3470
|
+
return GEMINI_LANGUAGE_NAMES[locale];
|
|
3572
3471
|
}
|
|
3573
3472
|
return locale;
|
|
3574
3473
|
}
|
|
@@ -3591,7 +3490,7 @@ function readImageAsBase64(imagePath) {
|
|
|
3591
3490
|
function getAspectRatioForDevice(deviceType) {
|
|
3592
3491
|
return DEVICE_ASPECT_RATIOS[deviceType];
|
|
3593
3492
|
}
|
|
3594
|
-
async function translateImage(sourcePath, sourceLocale, targetLocale,
|
|
3493
|
+
async function translateImage(sourcePath, sourceLocale, targetLocale, outputPaths, deviceType, preserveWords) {
|
|
3595
3494
|
try {
|
|
3596
3495
|
const client = getGeminiClient();
|
|
3597
3496
|
const sourceLanguage = getLanguageName(sourceLocale);
|
|
@@ -3650,14 +3549,17 @@ IMPORTANT INSTRUCTIONS:
|
|
|
3650
3549
|
for (const part of parts) {
|
|
3651
3550
|
if (part.inlineData?.data) {
|
|
3652
3551
|
const imageBuffer = Buffer.from(part.inlineData.data, "base64");
|
|
3653
|
-
const
|
|
3654
|
-
|
|
3655
|
-
fs10.
|
|
3552
|
+
for (const outputPath of outputPaths) {
|
|
3553
|
+
const outputDir = path10.dirname(outputPath);
|
|
3554
|
+
if (!fs10.existsSync(outputDir)) {
|
|
3555
|
+
fs10.mkdirSync(outputDir, { recursive: true });
|
|
3556
|
+
}
|
|
3557
|
+
await sharp(imageBuffer).png().toFile(outputPath);
|
|
3656
3558
|
}
|
|
3657
|
-
await sharp(imageBuffer).png().toFile(outputPath);
|
|
3658
3559
|
return {
|
|
3659
3560
|
success: true,
|
|
3660
|
-
outputPath
|
|
3561
|
+
outputPath: outputPaths[0]
|
|
3562
|
+
// Return primary path
|
|
3661
3563
|
};
|
|
3662
3564
|
}
|
|
3663
3565
|
}
|
|
@@ -3695,7 +3597,7 @@ async function translateImagesWithProgress(translations, onProgress, preserveWor
|
|
|
3695
3597
|
translation.sourcePath,
|
|
3696
3598
|
translation.sourceLocale,
|
|
3697
3599
|
translation.targetLocale,
|
|
3698
|
-
translation.
|
|
3600
|
+
translation.outputPaths,
|
|
3699
3601
|
translation.deviceType,
|
|
3700
3602
|
preserveWords
|
|
3701
3603
|
);
|
|
@@ -3717,6 +3619,81 @@ async function translateImagesWithProgress(translations, onProgress, preserveWor
|
|
|
3717
3619
|
return { successful, failed, errors };
|
|
3718
3620
|
}
|
|
3719
3621
|
|
|
3622
|
+
// src/tools/aso/utils/localize-screenshots/locale-mapping.constants.ts
|
|
3623
|
+
var GEMINI_LOCALE_GROUPS = {
|
|
3624
|
+
// English - covers all English variants
|
|
3625
|
+
"en-US": ["en-US", "en-AU", "en-CA", "en-GB", "en-IN", "en-SG", "en-ZA"],
|
|
3626
|
+
// Arabic - Gemini ar-EG → Unified ar
|
|
3627
|
+
"ar-EG": ["ar"],
|
|
3628
|
+
// German
|
|
3629
|
+
"de-DE": ["de-DE"],
|
|
3630
|
+
// Spanish - covers Latin America, Spain, and US Spanish
|
|
3631
|
+
"es-MX": ["es-419", "es-ES", "es-US"],
|
|
3632
|
+
// French - covers France and Canada
|
|
3633
|
+
"fr-FR": ["fr-FR", "fr-CA"],
|
|
3634
|
+
// Hindi
|
|
3635
|
+
"hi-IN": ["hi-IN"],
|
|
3636
|
+
// Indonesian
|
|
3637
|
+
"id-ID": ["id-ID"],
|
|
3638
|
+
// Italian
|
|
3639
|
+
"it-IT": ["it-IT"],
|
|
3640
|
+
// Japanese
|
|
3641
|
+
"ja-JP": ["ja-JP"],
|
|
3642
|
+
// Korean
|
|
3643
|
+
"ko-KR": ["ko-KR"],
|
|
3644
|
+
// Portuguese - covers Brazil and Portugal
|
|
3645
|
+
"pt-BR": ["pt-BR", "pt-PT"],
|
|
3646
|
+
// Russian
|
|
3647
|
+
"ru-RU": ["ru-RU"],
|
|
3648
|
+
// Ukrainian - Gemini ua-UA → Unified uk-UA
|
|
3649
|
+
"ua-UA": ["uk-UA"],
|
|
3650
|
+
// Vietnamese
|
|
3651
|
+
"vi-VN": ["vi-VN"],
|
|
3652
|
+
// Chinese - covers Simplified, Traditional, and Hong Kong
|
|
3653
|
+
"zh-CN": ["zh-Hans", "zh-Hant", "zh-HK"]
|
|
3654
|
+
};
|
|
3655
|
+
function getGeminiLocale(unifiedLocale) {
|
|
3656
|
+
for (const [geminiLocale, unifiedLocales] of Object.entries(
|
|
3657
|
+
GEMINI_LOCALE_GROUPS
|
|
3658
|
+
)) {
|
|
3659
|
+
if (unifiedLocales.includes(unifiedLocale)) {
|
|
3660
|
+
return geminiLocale;
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
return null;
|
|
3664
|
+
}
|
|
3665
|
+
function prepareLocalesForTranslation(locales, primaryLocale) {
|
|
3666
|
+
const targetLocales = locales.filter((l) => l !== primaryLocale);
|
|
3667
|
+
const localeMapping = /* @__PURE__ */ new Map();
|
|
3668
|
+
const geminiLocalesNeeded = /* @__PURE__ */ new Set();
|
|
3669
|
+
const skippedLocales = [];
|
|
3670
|
+
for (const locale of targetLocales) {
|
|
3671
|
+
const geminiLocale = getGeminiLocale(locale);
|
|
3672
|
+
if (geminiLocale === null) {
|
|
3673
|
+
skippedLocales.push(locale);
|
|
3674
|
+
continue;
|
|
3675
|
+
}
|
|
3676
|
+
geminiLocalesNeeded.add(geminiLocale);
|
|
3677
|
+
const existing = localeMapping.get(geminiLocale) || [];
|
|
3678
|
+
if (!existing.includes(locale)) {
|
|
3679
|
+
existing.push(locale);
|
|
3680
|
+
}
|
|
3681
|
+
localeMapping.set(geminiLocale, existing);
|
|
3682
|
+
}
|
|
3683
|
+
const groupedLocales = [];
|
|
3684
|
+
for (const [, unifiedLocales] of localeMapping) {
|
|
3685
|
+
if (unifiedLocales.length > 1) {
|
|
3686
|
+
groupedLocales.push(...unifiedLocales.slice(1));
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
return {
|
|
3690
|
+
translatableLocales: Array.from(geminiLocalesNeeded),
|
|
3691
|
+
localeMapping,
|
|
3692
|
+
skippedLocales,
|
|
3693
|
+
groupedLocales
|
|
3694
|
+
};
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3720
3697
|
// src/tools/aso/utils/localize-screenshots/image-resizer.util.ts
|
|
3721
3698
|
import sharp2 from "sharp";
|
|
3722
3699
|
import fs11 from "fs";
|
|
@@ -3927,7 +3904,7 @@ function getSupportedLocales(slug) {
|
|
|
3927
3904
|
};
|
|
3928
3905
|
}
|
|
3929
3906
|
function getTargetLocales(allLocales, primaryLocale, requestedTargets) {
|
|
3930
|
-
let
|
|
3907
|
+
let localesToProcess = allLocales;
|
|
3931
3908
|
if (requestedTargets && requestedTargets.length > 0) {
|
|
3932
3909
|
const validTargets = requestedTargets.filter((t) => allLocales.includes(t));
|
|
3933
3910
|
const invalidTargets = requestedTargets.filter(
|
|
@@ -3938,31 +3915,47 @@ function getTargetLocales(allLocales, primaryLocale, requestedTargets) {
|
|
|
3938
3915
|
`Warning: Some requested locales are not in product: ${invalidTargets.join(", ")}`
|
|
3939
3916
|
);
|
|
3940
3917
|
}
|
|
3941
|
-
|
|
3918
|
+
localesToProcess = validTargets;
|
|
3942
3919
|
}
|
|
3943
|
-
const
|
|
3944
|
-
|
|
3945
|
-
|
|
3920
|
+
const {
|
|
3921
|
+
translatableLocales,
|
|
3922
|
+
localeMapping,
|
|
3923
|
+
skippedLocales,
|
|
3924
|
+
groupedLocales
|
|
3925
|
+
} = prepareLocalesForTranslation(localesToProcess, primaryLocale);
|
|
3926
|
+
return {
|
|
3927
|
+
targets: translatableLocales,
|
|
3928
|
+
skippedLocales,
|
|
3929
|
+
groupedLocales,
|
|
3930
|
+
localeMapping
|
|
3931
|
+
};
|
|
3946
3932
|
}
|
|
3947
|
-
function buildTranslationTasks(slug, screenshots, primaryLocale, targetLocales, skipExisting) {
|
|
3933
|
+
function buildTranslationTasks(slug, screenshots, primaryLocale, targetLocales, localeMapping, skipExisting) {
|
|
3948
3934
|
const tasks = [];
|
|
3949
3935
|
const screenshotsDir = getScreenshotsDir(slug);
|
|
3950
3936
|
for (const targetLocale of targetLocales) {
|
|
3937
|
+
const outputLocales = localeMapping.get(targetLocale) || [];
|
|
3951
3938
|
for (const screenshot of screenshots) {
|
|
3952
|
-
const
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3939
|
+
const outputPaths = [];
|
|
3940
|
+
for (const locale of outputLocales) {
|
|
3941
|
+
const outputPath = path11.join(
|
|
3942
|
+
screenshotsDir,
|
|
3943
|
+
locale,
|
|
3944
|
+
screenshot.type,
|
|
3945
|
+
screenshot.filename
|
|
3946
|
+
);
|
|
3947
|
+
if (!skipExisting || !fs12.existsSync(outputPath)) {
|
|
3948
|
+
outputPaths.push(outputPath);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
if (outputPaths.length === 0) {
|
|
3959
3952
|
continue;
|
|
3960
3953
|
}
|
|
3961
3954
|
tasks.push({
|
|
3962
3955
|
sourcePath: screenshot.fullPath,
|
|
3963
3956
|
sourceLocale: primaryLocale,
|
|
3964
3957
|
targetLocale,
|
|
3965
|
-
|
|
3958
|
+
outputPaths,
|
|
3966
3959
|
deviceType: screenshot.type,
|
|
3967
3960
|
filename: screenshot.filename
|
|
3968
3961
|
});
|
|
@@ -4013,11 +4006,12 @@ async function handleLocalizeScreenshots(input) {
|
|
|
4013
4006
|
]
|
|
4014
4007
|
};
|
|
4015
4008
|
}
|
|
4016
|
-
const {
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4009
|
+
const {
|
|
4010
|
+
targets: targetLocales,
|
|
4011
|
+
skippedLocales,
|
|
4012
|
+
groupedLocales,
|
|
4013
|
+
localeMapping
|
|
4014
|
+
} = getTargetLocales(allLocales, primaryLocale, requestedTargetLocales);
|
|
4021
4015
|
if (targetLocales.length === 0) {
|
|
4022
4016
|
const skippedMsg = skippedLocales.length > 0 ? ` (Skipped due to Gemini limitation: ${skippedLocales.join(", ")})` : "";
|
|
4023
4017
|
return {
|
|
@@ -4029,9 +4023,16 @@ async function handleLocalizeScreenshots(input) {
|
|
|
4029
4023
|
]
|
|
4030
4024
|
};
|
|
4031
4025
|
}
|
|
4032
|
-
results.push(`\u{1F3AF} Target locales: ${targetLocales.join(", ")}`);
|
|
4026
|
+
results.push(`\u{1F3AF} Target locales to translate: ${targetLocales.join(", ")}`);
|
|
4027
|
+
if (groupedLocales.length > 0) {
|
|
4028
|
+
results.push(
|
|
4029
|
+
`\u{1F4CB} Grouped locales (saved together): ${groupedLocales.join(", ")}`
|
|
4030
|
+
);
|
|
4031
|
+
}
|
|
4033
4032
|
if (skippedLocales.length > 0) {
|
|
4034
|
-
results.push(
|
|
4033
|
+
results.push(
|
|
4034
|
+
`\u26A0\uFE0F Skipped locales (not supported by Gemini): ${skippedLocales.join(", ")}`
|
|
4035
|
+
);
|
|
4035
4036
|
}
|
|
4036
4037
|
const sourceScreenshots = scanLocaleScreenshots(appInfo.slug, primaryLocale);
|
|
4037
4038
|
let filteredScreenshots = sourceScreenshots.filter(
|
|
@@ -4089,6 +4090,7 @@ ${screenshotsDir2}/${primaryLocale}/tablet/1.png, 2.png, ...`
|
|
|
4089
4090
|
filteredScreenshots,
|
|
4090
4091
|
primaryLocale,
|
|
4091
4092
|
targetLocales,
|
|
4093
|
+
localeMapping,
|
|
4092
4094
|
skipExisting
|
|
4093
4095
|
);
|
|
4094
4096
|
if (tasks.length === 0) {
|
|
@@ -4117,8 +4119,11 @@ ${screenshotsDir2}/${primaryLocale}/tablet/1.png, 2.png, ...`
|
|
|
4117
4119
|
tasksByLocale[task.targetLocale].push(task);
|
|
4118
4120
|
}
|
|
4119
4121
|
for (const [locale, localeTasks] of Object.entries(tasksByLocale)) {
|
|
4122
|
+
const grouped = localeMapping.get(locale) || [];
|
|
4123
|
+
const groupedOthers = grouped.filter((l) => l !== locale);
|
|
4124
|
+
const groupInfo = groupedOthers.length > 0 ? ` \u2192 also: ${groupedOthers.join(", ")}` : "";
|
|
4120
4125
|
results.push(`
|
|
4121
|
-
\u{1F4C1} ${locale}:`);
|
|
4126
|
+
\u{1F4C1} ${locale}${groupInfo}:`);
|
|
4122
4127
|
for (const task of localeTasks) {
|
|
4123
4128
|
results.push(` - ${task.deviceType}/${task.filename}`);
|
|
4124
4129
|
}
|
|
@@ -4174,11 +4179,17 @@ ${screenshotsDir2}/${primaryLocale}/tablet/1.png, 2.png, ...`
|
|
|
4174
4179
|
if (translationResult.successful > 0) {
|
|
4175
4180
|
results.push(`
|
|
4176
4181
|
\u{1F50D} Validating image dimensions...`);
|
|
4177
|
-
const
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
+
const resizePairs = [];
|
|
4183
|
+
for (const task of tasks) {
|
|
4184
|
+
for (const outputPath of task.outputPaths) {
|
|
4185
|
+
if (fs12.existsSync(outputPath)) {
|
|
4186
|
+
resizePairs.push({
|
|
4187
|
+
sourcePath: task.sourcePath,
|
|
4188
|
+
translatedPath: outputPath
|
|
4189
|
+
});
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4182
4193
|
const resizeResult = await batchValidateAndResize(resizePairs);
|
|
4183
4194
|
if (resizeResult.resized > 0) {
|
|
4184
4195
|
results.push(` \u{1F527} Resized ${resizeResult.resized} images to match source dimensions`);
|