Skip to content

Instantly share code, notes, and snippets.

@dragoon
Created September 1, 2023 12:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dragoon/368b66af59e43620630a1eed36fad318 to your computer and use it in GitHub Desktop.
Save dragoon/368b66af59e43620630a1eed36fad318 to your computer and use it in GitHub Desktop.
Generate multi-language store listing file for Microsoft store.
import TranslateModule from '@google-cloud/translate';
import fs from 'fs';
import csv from 'fast-csv';
import path from 'path';
// Initialize Google Translate API Client
const translate = new TranslateModule.v2.Translate();
const screenshotDir = 'output/screenshots/';
process.env['GOOGLE_APPLICATION_CREDENTIALS'] = 'credentials.json';
async function translateText(text, target) {
let [translations] = await translate.translate(text, {from: "en", to: target});
return Array.isArray(translations) ? translations : [translations];
}
let screenshots = {};
fs.readdirSync(screenshotDir).forEach(dir => {
const lang = dir.toLowerCase();
const langDir = path.join(screenshotDir, dir);
if (fs.lstatSync(langDir).isDirectory()) {
screenshots[lang] = fs.readdirSync(langDir).map(f => path.join(langDir, f));
}
});
async function processRows() {
const data = [];
const rows = [];
return new Promise((resolve, reject) => {
fs.createReadStream('input.csv')
.pipe(csv.parse({ headers: true }))
.on('data', (row) => {
rows.push(row);
})
.on('end', () => {
resolve(rows);
})
.on('error', (error) => {
reject(error);
});
})
.then(async (rows) => {
for (let row of rows) {
let rowData = row;
for (let lang of Object.keys(screenshots)) {
if (rowData[lang]) continue; // Don't translate if there's existing data
if (rowData["Field"] === "StoreLogo300x300") {
rowData[lang] = "output/windows_tile_icon.png";
}
else if (rowData["Field"].startsWith("DesktopScreenshot") && screenshots[lang]) {
rowData[lang] = screenshots[lang].shift(); // Assign screenshot path and remove from array
}
else if (rowData["Field"] === "ShortTitle" || rowData["Field"] === "SortTitle") {
rowData[lang] = row["en-us"];
} else {
if (lang.startsWith("en")) {
rowData[lang] = rowData["en-us"];
continue;
}
if (!row['en-us']) {
rowData[lang] = '';
continue;
}
if (rowData["Field"] === "Title") {
rowData[lang] = row['en-us'];
} else {
rowData[lang] = await translateText(row['en-us'], lang);
}
}
}
data.push(rowData);
}
return data;
});
}
async function main() {
try {
const data = await processRows();
csv.writeToPath("output/out.csv", data, { headers: true })
.on("finish", function() {
console.log("The CSV file was written successfully");
});
} catch (error) {
console.error("Error processing rows:", error);
}
}
main();
@dragoon
Copy link
Author

dragoon commented Sep 1, 2023

Requires input.csv seed file with "en-us" column filled, e.g.:

Field,ID,Type (Type),default,en-us
Description,2,Text,,"An ultimate home dashboard with time, calendar, five-day weather forecast, day/night modes, UV and precipitation forecasts, and more."
ReleaseNotes,3,Text,,
Title,4,Text,,Zima Weather
ShortTitle,5,Text,,Zima
SortTitle,6,Text,,Zima
VoiceTitle,7,Text,,
ShortDescription,8,Text,,
DevStudio,9,Text,,
CopyrightTrademarkInformation,12,Text,,
AdditionalLicenseTerms,13,Text,,
DesktopScreenshot1,100,Relative path (or URL to file in Partner Center),,
DesktopScreenshot2,101,Relative path (or URL to file in Partner Center),,
DesktopScreenshot3,102,Relative path (or URL to file in Partner Center),,
DesktopScreenshot4,103,Relative path (or URL to file in Partner Center),,
DesktopScreenshot5,104,Relative path (or URL to file in Partner Center),,
DesktopScreenshotCaption1,150,Text,,
DesktopScreenshotCaption2,151,Text,,
DesktopScreenshotCaption3,152,Text,,
DesktopScreenshotCaption4,153,Text,,
DesktopScreenshotCaption5,154,Text,,
Feature1,700,Text,,weather
Feature2,701,Text,,calendar
Feature3,702,Text,,sunset/sunrise
Feature4,703,Text,,moon phases
Feature5,704,Text,,holidays
SearchTerm1,900,Text,,weather
SearchTerm2,901,Text,,calendar
SearchTerm3,902,Text,,holidays
StoreLogo300x300,602,Relative path (or URL to file in Partner Center),,
TrailerToPlayAtTopOfListing,999,Relative path (or URL to file in Partner Center),,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment