pabal-web-mcp 1.4.5 → 1.4.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.
@@ -1620,16 +1620,35 @@ ${primaryResearchSections.join("\n")}
1620
1620
 
1621
1621
  `;
1622
1622
  }
1623
+ const { keywordResearchFallbackByLocale } = args;
1623
1624
  nonPrimaryLocales.forEach((loc) => {
1624
1625
  const researchSections = keywordResearchByLocale[loc] || [];
1625
1626
  const researchDir = keywordResearchDirByLocale[loc];
1627
+ const fallbackInfo = keywordResearchFallbackByLocale?.[loc];
1626
1628
  if (researchSections.length > 0) {
1627
- prompt += `### Locale ${loc}: \u2705 Saved research found
1629
+ if (fallbackInfo?.isFallback && fallbackInfo.fallbackLocale) {
1630
+ prompt += `### Locale ${loc}: \u{1F504} Using ${fallbackInfo.fallbackLocale} keywords as fallback - MUST TRANSLATE TO ${loc.toUpperCase()}
1631
+ `;
1632
+ prompt += researchSections.join("\n");
1633
+ prompt += `
1634
+
1635
+ **CRITICAL:** The keywords above are in ${fallbackInfo.fallbackLocale}. You MUST:
1636
+ `;
1637
+ prompt += `1. **TRANSLATE each keyword into ${loc}** - use natural, native expressions
1638
+ `;
1639
+ prompt += `2. Ensure translated keywords are what ${loc} users would actually search for
1640
+ `;
1641
+ prompt += `3. **DO NOT use ${fallbackInfo.fallbackLocale} keywords directly** - all keywords must be in ${loc} language
1642
+
1643
+ `;
1644
+ } else {
1645
+ prompt += `### Locale ${loc}: \u2705 Saved research found (locale-specific)
1628
1646
  ${researchSections.join(
1629
- "\n"
1630
- )}
1647
+ "\n"
1648
+ )}
1631
1649
 
1632
1650
  `;
1651
+ }
1633
1652
  } else if (hasPrimaryResearch) {
1634
1653
  prompt += `### Locale ${loc}: \u26A0\uFE0F No saved research - TRANSLATE ENGLISH KEYWORDS TO ${loc.toUpperCase()}
1635
1654
  `;
@@ -2130,7 +2149,7 @@ function formatMergedData(merged, researchDir) {
2130
2149
  lines.push("\n----");
2131
2150
  return lines.join("\n");
2132
2151
  }
2133
- function loadKeywordResearchForLocale(slug, locale) {
2152
+ function loadKeywordResearchForLocaleInternal(slug, locale) {
2134
2153
  const researchDir = path6.join(
2135
2154
  getKeywordResearchDir(),
2136
2155
  "products",
@@ -2139,9 +2158,12 @@ function loadKeywordResearchForLocale(slug, locale) {
2139
2158
  locale
2140
2159
  );
2141
2160
  if (!fs6.existsSync(researchDir)) {
2142
- return { entries: [], sections: [], researchDir };
2161
+ return null;
2143
2162
  }
2144
2163
  const files = fs6.readdirSync(researchDir).filter((file) => file.endsWith(".json"));
2164
+ if (files.length === 0) {
2165
+ return null;
2166
+ }
2145
2167
  const entries = [];
2146
2168
  for (const file of files) {
2147
2169
  const filePath = path6.join(researchDir, file);
@@ -2159,17 +2181,53 @@ function loadKeywordResearchForLocale(slug, locale) {
2159
2181
  }
2160
2182
  }
2161
2183
  const validEntries = entries.filter((e) => !e.data?.parseError);
2184
+ if (validEntries.length === 0) {
2185
+ return null;
2186
+ }
2162
2187
  if (validEntries.length > 1) {
2163
2188
  const merged = mergeKeywordData(validEntries);
2164
2189
  const mergedSection = formatMergedData(merged, researchDir);
2165
2190
  return { entries, sections: [mergedSection], researchDir };
2166
- } else if (validEntries.length === 1) {
2167
- const sections2 = entries.map(formatEntry);
2168
- return { entries, sections: sections2, researchDir };
2169
2191
  }
2170
2192
  const sections = entries.map(formatEntry);
2171
2193
  return { entries, sections, researchDir };
2172
2194
  }
2195
+ var FALLBACK_LOCALES = ["en-US", "en"];
2196
+ function loadKeywordResearchForLocale(slug, locale) {
2197
+ const researchDir = path6.join(
2198
+ getKeywordResearchDir(),
2199
+ "products",
2200
+ slug,
2201
+ "locales",
2202
+ locale
2203
+ );
2204
+ const result = loadKeywordResearchForLocaleInternal(slug, locale);
2205
+ if (result) {
2206
+ return { ...result, isFallback: false };
2207
+ }
2208
+ for (const fallbackLocale of FALLBACK_LOCALES) {
2209
+ if (fallbackLocale === locale) continue;
2210
+ const fallbackResult = loadKeywordResearchForLocaleInternal(
2211
+ slug,
2212
+ fallbackLocale
2213
+ );
2214
+ if (fallbackResult) {
2215
+ const fallbackNotice = `\u26A0\uFE0F **FALLBACK: Using ${fallbackLocale} keywords** - No research found for ${locale}. You MUST TRANSLATE these keywords to ${locale}.
2216
+ `;
2217
+ const sectionsWithNotice = fallbackResult.sections.map(
2218
+ (section) => fallbackNotice + section
2219
+ );
2220
+ return {
2221
+ entries: fallbackResult.entries,
2222
+ sections: sectionsWithNotice,
2223
+ researchDir: fallbackResult.researchDir,
2224
+ isFallback: true,
2225
+ fallbackLocale
2226
+ };
2227
+ }
2228
+ }
2229
+ return { entries: [], sections: [], researchDir, isFallback: false };
2230
+ }
2173
2231
 
2174
2232
  // src/tools/improve-public.ts
2175
2233
  var toJsonSchema3 = zodToJsonSchema3;
@@ -2279,10 +2337,15 @@ async function handleImprovePublic(input) {
2279
2337
  }
2280
2338
  const keywordResearchByLocale = {};
2281
2339
  const keywordResearchDirByLocale = {};
2340
+ const keywordResearchFallbackByLocale = {};
2282
2341
  for (const loc of targetLocales) {
2283
2342
  const research = loadKeywordResearchForLocale(slug, loc);
2284
2343
  keywordResearchByLocale[loc] = research.sections;
2285
2344
  keywordResearchDirByLocale[loc] = research.researchDir;
2345
+ keywordResearchFallbackByLocale[loc] = {
2346
+ isFallback: research.isFallback,
2347
+ fallbackLocale: research.fallbackLocale
2348
+ };
2286
2349
  }
2287
2350
  const baseArgs = {
2288
2351
  slug,
@@ -2291,7 +2354,8 @@ async function handleImprovePublic(input) {
2291
2354
  targetLocales,
2292
2355
  localeSections,
2293
2356
  keywordResearchByLocale,
2294
- keywordResearchDirByLocale
2357
+ keywordResearchDirByLocale,
2358
+ keywordResearchFallbackByLocale
2295
2359
  };
2296
2360
  if (stage === "1" || stage === "both") {
2297
2361
  const prompt = generatePrimaryOptimizationPrompt(baseArgs);
@@ -2339,6 +2403,7 @@ async function handleImprovePublic(input) {
2339
2403
  localeSections: baseArgs.localeSections,
2340
2404
  keywordResearchByLocale: baseArgs.keywordResearchByLocale,
2341
2405
  keywordResearchDirByLocale: baseArgs.keywordResearchDirByLocale,
2406
+ keywordResearchFallbackByLocale: baseArgs.keywordResearchFallbackByLocale,
2342
2407
  optimizedPrimary,
2343
2408
  batchLocales,
2344
2409
  batchIndex: currentBatchIndex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pabal-web-mcp",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "type": "module",
5
5
  "description": "MCP server for ASO data management with shared types and utilities",
6
6
  "author": "skyu",