@el-j/google-sheet-translations 1.3.3 → 2.0.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.
Files changed (60) hide show
  1. package/README.md +58 -55
  2. package/dist/action-entrypoint.d.ts +2 -0
  3. package/dist/action-entrypoint.d.ts.map +1 -0
  4. package/dist/esm/index.js +1226 -0
  5. package/dist/esm/package.json +1 -0
  6. package/dist/index.d.ts +8 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1288 -41
  9. package/dist/utils/dataConverter/findLocalChanges.d.ts +2 -1
  10. package/dist/utils/dataConverter/findLocalChanges.d.ts.map +1 -1
  11. package/dist/utils/localeNormalizer.d.ts +31 -0
  12. package/dist/utils/localeNormalizer.d.ts.map +1 -1
  13. package/dist/utils/translationHelpers.d.ts +107 -0
  14. package/dist/utils/translationHelpers.d.ts.map +1 -0
  15. package/package.json +21 -14
  16. package/dist/constants.js +0 -9
  17. package/dist/constants.js.map +0 -1
  18. package/dist/getSpreadSheetData.js +0 -170
  19. package/dist/getSpreadSheetData.js.map +0 -1
  20. package/dist/index.js.map +0 -1
  21. package/dist/types.js +0 -3
  22. package/dist/types.js.map +0 -1
  23. package/dist/utils/auth.js +0 -23
  24. package/dist/utils/auth.js.map +0 -1
  25. package/dist/utils/configurationHandler.js +0 -29
  26. package/dist/utils/configurationHandler.js.map +0 -1
  27. package/dist/utils/dataConverter/convertFromDataJsonFormat.js +0 -47
  28. package/dist/utils/dataConverter/convertFromDataJsonFormat.js.map +0 -1
  29. package/dist/utils/dataConverter/convertToDataJsonFormat.js +0 -51
  30. package/dist/utils/dataConverter/convertToDataJsonFormat.js.map +0 -1
  31. package/dist/utils/dataConverter/findLocalChanges.js +0 -70
  32. package/dist/utils/dataConverter/findLocalChanges.js.map +0 -1
  33. package/dist/utils/fileWriter.js +0 -119
  34. package/dist/utils/fileWriter.js.map +0 -1
  35. package/dist/utils/getFileLastModified.js +0 -23
  36. package/dist/utils/getFileLastModified.js.map +0 -1
  37. package/dist/utils/isDataJsonNewer.js +0 -40
  38. package/dist/utils/isDataJsonNewer.js.map +0 -1
  39. package/dist/utils/localeFilter.js +0 -49
  40. package/dist/utils/localeFilter.js.map +0 -1
  41. package/dist/utils/localeNormalizer.js +0 -176
  42. package/dist/utils/localeNormalizer.js.map +0 -1
  43. package/dist/utils/publicSheetReader.js +0 -109
  44. package/dist/utils/publicSheetReader.js.map +0 -1
  45. package/dist/utils/rateLimiter.js +0 -55
  46. package/dist/utils/rateLimiter.js.map +0 -1
  47. package/dist/utils/readDataJson.js +0 -29
  48. package/dist/utils/readDataJson.js.map +0 -1
  49. package/dist/utils/sheetProcessor.js +0 -121
  50. package/dist/utils/sheetProcessor.js.map +0 -1
  51. package/dist/utils/spreadsheetCreator.js +0 -121
  52. package/dist/utils/spreadsheetCreator.js.map +0 -1
  53. package/dist/utils/spreadsheetUpdater.js +0 -227
  54. package/dist/utils/spreadsheetUpdater.js.map +0 -1
  55. package/dist/utils/syncManager.js +0 -62
  56. package/dist/utils/syncManager.js.map +0 -1
  57. package/dist/utils/validateEnv.js +0 -41
  58. package/dist/utils/validateEnv.js.map +0 -1
  59. package/dist/utils/wait.js +0 -19
  60. package/dist/utils/wait.js.map +0 -1
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findLocalChanges = findLocalChanges;
4
- const localeNormalizer_1 = require("../localeNormalizer");
5
- /**
6
- * Resolves a locale key from `localData` to the corresponding key actually
7
- * present in `spreadsheetData`, using a three-step strategy:
8
- *
9
- * 1. Exact match – `'en-us'` → `'en-us'`
10
- * 2. Lowercase match – `'en-US'` → `'en-us'`
11
- * 3. Language-family prefix – `'en'` or `'en-GB'` → `'en-us'`
12
- * (when `'en-us'` is the only English variant in the spreadsheet data)
13
- *
14
- * Returns `undefined` when no matching locale exists in `spreadsheetData`.
15
- */
16
- function resolveLocaleAlias(locale, spreadsheetData) {
17
- if (spreadsheetData[locale])
18
- return locale;
19
- const lower = locale.toLowerCase();
20
- if (spreadsheetData[lower])
21
- return lower;
22
- const langCode = (0, localeNormalizer_1.getLanguagePrefix)(lower);
23
- return Object.keys(spreadsheetData).find((k) => (0, localeNormalizer_1.getLanguagePrefix)(k) === langCode);
24
- }
25
- /**
26
- * Compares local languageData.json with spreadsheet data to find new keys.
27
- *
28
- * A key is considered "new" when:
29
- * - No matching locale exists in `spreadsheetData` for that locale, OR
30
- * - The sheet or key is absent for the resolved locale.
31
- *
32
- * Locale matching is fuzzy: `'en'` and `'en-GB'` will both match against
33
- * an `'en-us'` entry in `spreadsheetData` (language-family resolution).
34
- *
35
- * @param localData - Data from local languageData.json file
36
- * @param spreadsheetData - Data fetched from the spreadsheet
37
- * @returns Object with new keys that are in localData but not in spreadsheetData
38
- */
39
- function findLocalChanges(localData, spreadsheetData) {
40
- const changes = {};
41
- // Check each locale in local data
42
- for (const locale of Object.keys(localData)) {
43
- if (!localData[locale])
44
- continue;
45
- // Resolve the locale to the matching key in spreadsheetData (fuzzy match)
46
- const resolvedLocale = resolveLocaleAlias(locale, spreadsheetData);
47
- // Check each sheet in local data
48
- for (const sheet of Object.keys(localData[locale])) {
49
- if (!localData[locale][sheet])
50
- continue;
51
- // Check each key in local data
52
- for (const key of Object.keys(localData[locale][sheet])) {
53
- // If the spreadsheet doesn't have this locale, sheet, or key, it's a new key
54
- const isNewKey = !resolvedLocale ||
55
- !spreadsheetData[resolvedLocale]?.[sheet] ||
56
- !spreadsheetData[resolvedLocale][sheet][key];
57
- // If it's a new key, add it to changes
58
- if (isNewKey) {
59
- if (!changes[locale])
60
- changes[locale] = {};
61
- if (!changes[locale][sheet])
62
- changes[locale][sheet] = {};
63
- changes[locale][sheet][key] = localData[locale][sheet][key];
64
- }
65
- }
66
- }
67
- }
68
- return changes;
69
- }
70
- //# sourceMappingURL=findLocalChanges.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"findLocalChanges.js","sourceRoot":"","sources":["../../../src/utils/dataConverter/findLocalChanges.ts"],"names":[],"mappings":";;AAyCA,4CAmCC;AA3ED,0DAAwD;AAExD;;;;;;;;;;GAUG;AACH,SAAS,kBAAkB,CAC1B,MAAc,EACd,eAAgC;IAEhC,IAAI,eAAe,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAA,oCAAiB,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,oCAAiB,EAAC,CAAC,CAAC,KAAK,QAAQ,CACxC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,gBAAgB,CAC/B,SAA0B,EAC1B,eAAgC;IAEhC,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,kCAAkC;IAClC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAAE,SAAS;QAEjC,0EAA0E;QAC1E,MAAM,cAAc,GAAG,kBAAkB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAEnE,iCAAiC;QACjC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;gBAAE,SAAS;YAExC,+BAA+B;YAC/B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzD,6EAA6E;gBAC7E,MAAM,QAAQ,GAAG,CAAC,cAAc;oBAC/B,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC;oBACzC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;gBAE9C,uCAAuC;gBACvC,IAAI,QAAQ,EAAE,CAAC;oBACd,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;wBAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;oBAC3C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;wBAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;oBACzD,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC7D,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC"}
@@ -1,119 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writeTranslationFiles = writeTranslationFiles;
7
- exports.writeLocalesFile = writeLocalesFile;
8
- exports.writeLanguageDataFile = writeLanguageDataFile;
9
- const node_fs_1 = __importDefault(require("node:fs"));
10
- const node_path_1 = __importDefault(require("node:path"));
11
- const convertToDataJsonFormat_1 = require("./dataConverter/convertToDataJsonFormat");
12
- /**
13
- * Writes locale files to the translations directory
14
- * @param translations Translation data organized by locale
15
- * @param locales Array of locale identifiers
16
- * @param translationsOutputDir Directory to write translation files to
17
- */
18
- function writeTranslationFiles(translations, locales, translationsOutputDir) {
19
- // Make sure the translations directory exists
20
- if (!node_fs_1.default.existsSync(translationsOutputDir)) {
21
- try {
22
- node_fs_1.default.mkdirSync(translationsOutputDir, { recursive: true });
23
- }
24
- catch (err) {
25
- throw new Error(`Failed to create translations directory "${translationsOutputDir}"`, { cause: err });
26
- }
27
- }
28
- // Write files for all locales
29
- for (const locale of locales) {
30
- if (!translations[locale] || Object.keys(translations[locale]).length === 0) {
31
- console.warn(`No translations found for locale "${locale}"`);
32
- continue;
33
- }
34
- // Sanitize locale to prevent path traversal attacks
35
- const safeName = locale.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
36
- if (safeName !== locale.toLowerCase()) {
37
- console.warn(`Locale "${locale}" contained unsafe characters; sanitised to "${safeName}"`);
38
- }
39
- try {
40
- node_fs_1.default.writeFileSync(node_path_1.default.join(translationsOutputDir, `${safeName}.json`), JSON.stringify(translations[locale], null, 2), "utf8");
41
- console.log(`Successfully wrote translations for ${locale}`);
42
- }
43
- catch (err) {
44
- console.error(`Failed to write translation file for locale "${locale}" at "${node_path_1.default.join(translationsOutputDir, `${safeName}.json`)}":`, err);
45
- }
46
- }
47
- }
48
- /**
49
- * Writes the locales.ts file containing the array of available locales and header mapping
50
- * @param locales Array of normalized locale identifiers (filtered to only include valid locales)
51
- * @param localeMapping Mapping from normalized locales to original spreadsheet headers
52
- * @param localesOutputPath Path to write the locales.ts file
53
- */
54
- function writeLocalesFile(locales, localeMapping, localesOutputPath) {
55
- // Create locales.ts file directory if it doesn't exist
56
- const localesOutputDir = node_path_1.default.dirname(localesOutputPath);
57
- if (!node_fs_1.default.existsSync(localesOutputDir)) {
58
- try {
59
- node_fs_1.default.mkdirSync(localesOutputDir, { recursive: true });
60
- }
61
- catch (err) {
62
- throw new Error(`Failed to create directory "${localesOutputDir}"`, { cause: err });
63
- }
64
- }
65
- const validLocales = locales.filter(locale => locale && locale.trim().length > 0);
66
- // Create the content with both locales and header mapping
67
- const content = `/**
68
- * This file is auto-generated from the Google Spreadsheet package.
69
- * It contains the list of available locales and their mappings to original spreadsheet headers.
70
- * Do not edit this file manually, it will be overwritten by the package.
71
- */
72
-
73
- export const locales = ${JSON.stringify(validLocales)};
74
-
75
- /**
76
- * Mapping from normalized locale codes to original spreadsheet headers
77
- * Used for syncing changes back to the spreadsheet
78
- */
79
- export const localeHeaderMapping = ${JSON.stringify(localeMapping, null, 2)};
80
-
81
- export default locales;
82
- `;
83
- try {
84
- node_fs_1.default.writeFileSync(localesOutputPath, content, "utf8");
85
- }
86
- catch (err) {
87
- throw new Error(`Failed to write locales file at "${localesOutputPath}"`, { cause: err });
88
- }
89
- console.log(`Successfully wrote locales file with ${validLocales.length} locales:`, validLocales);
90
- console.log('Header mapping includes:', Object.keys(localeMapping).length, 'mappings');
91
- }
92
- /**
93
- * Writes the languageData.json file containing all translation data
94
- * @param translations Translation data organized by locale
95
- * @param locales Array of locale identifiers
96
- * @param dataJsonPath Path to write the languageData.json file
97
- */
98
- function writeLanguageDataFile(translations, locales, dataJsonPath) {
99
- // Create languageData.json directory if it doesn't exist
100
- const dataJsonDir = node_path_1.default.dirname(dataJsonPath);
101
- if (!node_fs_1.default.existsSync(dataJsonDir)) {
102
- try {
103
- node_fs_1.default.mkdirSync(dataJsonDir, { recursive: true });
104
- }
105
- catch (err) {
106
- throw new Error(`Failed to create directory "${dataJsonDir}"`, { cause: err });
107
- }
108
- }
109
- // Convert the object format to the array format expected in languageData.json
110
- const dataJsonContent = (0, convertToDataJsonFormat_1.convertToDataJsonFormat)(translations, locales);
111
- try {
112
- node_fs_1.default.writeFileSync(dataJsonPath, JSON.stringify(dataJsonContent, null, 2), "utf8");
113
- }
114
- catch (err) {
115
- throw new Error(`Failed to write language data file at "${dataJsonPath}"`, { cause: err });
116
- }
117
- console.log("Successfully updated languageData.json with fresh spreadsheet data");
118
- }
119
- //# sourceMappingURL=fileWriter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileWriter.js","sourceRoot":"","sources":["../../src/utils/fileWriter.ts"],"names":[],"mappings":"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"}
@@ -1,23 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getFileLastModified = getFileLastModified;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- /**
9
- * Gets the last modified time of a file
10
- * @param filePath - Path to the file
11
- * @returns The last modified time as a Date object, or null if file doesn't exist
12
- */
13
- function getFileLastModified(filePath) {
14
- try {
15
- const stats = node_fs_1.default.statSync(filePath);
16
- return stats.mtime;
17
- }
18
- catch (error) {
19
- console.warn(`Could not read file stats for "${filePath}":`, error);
20
- return null;
21
- }
22
- }
23
- //# sourceMappingURL=getFileLastModified.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getFileLastModified.js","sourceRoot":"","sources":["../../src/utils/getFileLastModified.ts"],"names":[],"mappings":";;;;;AAOA,kDAQC;AAfD,sDAAyB;AAEzB;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,QAAgB;IACnD,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,iBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,KAAK,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,kCAAkC,QAAQ,IAAI,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -1,40 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.isDataJsonNewer = isDataJsonNewer;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- const getFileLastModified_1 = require("./getFileLastModified");
10
- /**
11
- * Checks if languageData.json has been modified more recently than the translation files
12
- * @param dataJsonPath - Path to languageData.json
13
- * @param translationsOutputDir - Directory containing translation files
14
- * @returns True if languageData.json is newer than the translation files
15
- */
16
- function isDataJsonNewer(dataJsonPath, translationsOutputDir) {
17
- const dataJsonMtime = (0, getFileLastModified_1.getFileLastModified)(dataJsonPath);
18
- if (!dataJsonMtime)
19
- return false;
20
- // Get the most recent translation file modification time
21
- try {
22
- const files = node_fs_1.default.readdirSync(translationsOutputDir)
23
- .filter(file => file.endsWith('.json'))
24
- .map(file => node_path_1.default.join(translationsOutputDir, file));
25
- if (files.length === 0)
26
- return true;
27
- const mostRecentTranslationMtime = files
28
- .map(file => (0, getFileLastModified_1.getFileLastModified)(file))
29
- .filter((d) => d !== null)
30
- .reduce((max, d) => (max === null || d > max ? d : max), null);
31
- if (!mostRecentTranslationMtime)
32
- return true;
33
- return dataJsonMtime > mostRecentTranslationMtime;
34
- }
35
- catch (error) {
36
- console.warn("Error comparing file modification times:", error);
37
- return false;
38
- }
39
- }
40
- //# sourceMappingURL=isDataJsonNewer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"isDataJsonNewer.js","sourceRoot":"","sources":["../../src/utils/isDataJsonNewer.ts"],"names":[],"mappings":";;;;;AAUA,0CA2BC;AArCD,sDAAyB;AACzB,0DAA6B;AAC7B,+DAA4D;AAE5D;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,YAAoB,EAAE,qBAA6B;IAClF,MAAM,aAAa,GAAG,IAAA,yCAAmB,EAAC,YAAY,CAAC,CAAC;IAExD,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAEjC,yDAAyD;IACzD,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,iBAAE,CAAC,WAAW,CAAC,qBAAqB,CAAC;aACjD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aACtC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC,CAAC;QAEtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,0BAA0B,GAAG,KAAK;aACtC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,yCAAmB,EAAC,IAAI,CAAC,CAAC;aACtC,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;aACpC,MAAM,CACN,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAC/C,IAAI,CACJ,CAAC;QAEH,IAAI,CAAC,0BAA0B;YAAE,OAAO,IAAI,CAAC;QAC7C,OAAO,aAAa,GAAG,0BAA0B,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;QAChE,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -1,49 +0,0 @@
1
- "use strict";
2
- /**
3
- * Locale validation utilities
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.isValidLocale = isValidLocale;
7
- exports.filterValidLocales = filterValidLocales;
8
- const COMMON_LOCALE_PATTERNS = [
9
- /^[a-z]{2}$/, // en, de, fr
10
- /^[a-z]{2}-[a-z]{2}$/, // en-us, de-de
11
- /^[a-z]{2}_[a-z]{2}$/, // en_us, de_de
12
- /^[a-z]{2}-[a-z]{2}-[a-z]+$/, // en-us-traditional
13
- ];
14
- const NON_LOCALE_KEYWORDS = [
15
- 'key', 'keys', 'id', 'identifier', 'name', 'title', 'label',
16
- 'description', 'comment', 'note', 'context', 'category', 'type',
17
- 'status', 'updated', 'created', 'modified', 'version', 'source',
18
- 'i18n', 'translation', 'namespace', 'section'
19
- ];
20
- /**
21
- * Determines if a string represents a valid locale identifier
22
- * @param value The string to test
23
- * @returns true if the string appears to be a locale identifier
24
- */
25
- function isValidLocale(value) {
26
- if (!value || typeof value !== 'string') {
27
- return false;
28
- }
29
- const normalized = value.toLowerCase().trim();
30
- // Check if it's a common non-locale keyword
31
- if (NON_LOCALE_KEYWORDS.includes(normalized)) {
32
- return false;
33
- }
34
- // Check if it matches common locale patterns (only accept lowercase patterns)
35
- return COMMON_LOCALE_PATTERNS.some(pattern => pattern.test(normalized));
36
- }
37
- /**
38
- * Filters header row to only include valid locale columns, excluding the key column
39
- * @param headerRow Array of column names from the sheet header
40
- * @param keyColumn The name of the key column to exclude
41
- * @returns Array of valid locale identifiers
42
- */
43
- function filterValidLocales(headerRow, keyColumn) {
44
- return headerRow
45
- .filter(column => column.toLowerCase() !== keyColumn.toLowerCase())
46
- .filter(column => isValidLocale(column)) // Use original case for validation
47
- .map(locale => locale.toLowerCase()); // Then normalize to lowercase
48
- }
49
- //# sourceMappingURL=localeFilter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localeFilter.js","sourceRoot":"","sources":["../../src/utils/localeFilter.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAqBH,sCAcC;AAQD,gDAKC;AA9CD,MAAM,sBAAsB,GAAG;IAC9B,YAAY,EAAqB,aAAa;IAC9C,qBAAqB,EAAW,eAAe;IAC/C,qBAAqB,EAAW,eAAe;IAC/C,4BAA4B,EAAI,oBAAoB;CACpD,CAAC;AAEF,MAAM,mBAAmB,GAAG;IAC3B,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAC3D,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM;IAC/D,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ;IAC/D,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS;CAC7C,CAAC;AAEF;;;;GAIG;AACH,SAAgB,aAAa,CAAC,KAAa;IAC1C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE9C,4CAA4C;IAC5C,IAAI,mBAAmB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACd,CAAC;IAED,8EAA8E;IAC9E,OAAO,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,SAAmB,EAAE,SAAiB;IACxE,OAAO,SAAS;SACd,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC;SAClE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,mCAAmC;SAC3E,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,8BAA8B;AACtE,CAAC"}
@@ -1,176 +0,0 @@
1
- "use strict";
2
- /**
3
- * Locale normalization utilities for converting simple language codes to full locale codes
4
- * and maintaining mappings between normalized codes and original spreadsheet headers
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getLanguagePrefix = getLanguagePrefix;
8
- exports.normalizeLocaleCode = normalizeLocaleCode;
9
- exports.createLocaleMapping = createLocaleMapping;
10
- exports.getOriginalHeaderForLocale = getOriginalHeaderForLocale;
11
- exports.getNormalizedLocaleForHeader = getNormalizedLocaleForHeader;
12
- /**
13
- * Returns the language prefix of a locale code (the part before the first
14
- * `-` or `_` separator), lowercased.
15
- *
16
- * Examples:
17
- * - `'en-US'` → `'en'`
18
- * - `'zh_CN'` → `'zh'`
19
- * - `'de'` → `'de'`
20
- *
21
- * Used for language-family matching when an exact locale code is not found.
22
- */
23
- function getLanguagePrefix(locale) {
24
- return locale.toLowerCase().split(/[-_]/)[0];
25
- }
26
- /**
27
- * Common language to country mappings for normalization
28
- * Maps language codes to their most common country variants
29
- */
30
- const LANGUAGE_TO_COUNTRY_MAP = {
31
- 'en': 'en-GB',
32
- 'de': 'de-DE',
33
- 'fr': 'fr-FR',
34
- 'es': 'es-ES',
35
- 'it': 'it-IT',
36
- 'pt': 'pt-PT',
37
- 'pl': 'pl-PL',
38
- 'ru': 'ru-RU',
39
- 'zh': 'zh-CN',
40
- 'ja': 'ja-JP',
41
- 'ko': 'ko-KR',
42
- 'ar': 'ar-SA',
43
- 'hi': 'hi-IN',
44
- 'th': 'th-TH',
45
- 'vi': 'vi-VN',
46
- 'tr': 'tr-TR',
47
- 'nl': 'nl-NL',
48
- 'sv': 'sv-SE',
49
- 'da': 'da-DK',
50
- 'no': 'no-NO',
51
- 'fi': 'fi-FI',
52
- 'cs': 'cs-CZ',
53
- 'sk': 'sk-SK',
54
- 'hu': 'hu-HU',
55
- 'ro': 'ro-RO',
56
- 'bg': 'bg-BG',
57
- 'hr': 'hr-HR',
58
- 'sl': 'sl-SI',
59
- 'et': 'et-EE',
60
- 'lv': 'lv-LV',
61
- 'lt': 'lt-LT',
62
- 'el': 'el-GR',
63
- 'he': 'he-IL',
64
- 'uk': 'uk-UA',
65
- 'be': 'be-BY',
66
- };
67
- /**
68
- * Normalizes a language code to include country code if missing
69
- * @param locale The original locale code from spreadsheet header
70
- * @returns Normalized locale with country code
71
- */
72
- function normalizeLocaleCode(locale) {
73
- if (!locale || typeof locale !== 'string') {
74
- return '';
75
- }
76
- const normalized = locale.toLowerCase().trim();
77
- // If already has country code, return as is
78
- if (normalized.includes('-') || normalized.includes('_')) {
79
- return normalized;
80
- }
81
- // Look up the language in our mapping first
82
- const withCountry = LANGUAGE_TO_COUNTRY_MAP[normalized];
83
- if (withCountry) {
84
- return withCountry;
85
- }
86
- // If not in mapping and it's a 2-letter code, append the same code in uppercase
87
- // This handles cases like "pl" -> "pl-PL"
88
- if (normalized.length === 2 && /^[a-z]{2}$/.test(normalized)) {
89
- return `${normalized}-${normalized.toUpperCase()}`;
90
- }
91
- // Return original if we can't normalize it
92
- return normalized;
93
- }
94
- /**
95
- * Creates a mapping between normalized locale codes and their original spreadsheet headers
96
- * @param originalHeaders Array of original header names from spreadsheet
97
- * @param keyColumn The key column name to exclude
98
- * @returns Object with normalized locales and header mapping
99
- */
100
- function createLocaleMapping(originalHeaders, keyColumn) {
101
- const localeMapping = {}; // normalized -> original
102
- const originalMapping = {}; // original -> normalized
103
- const normalizedLocales = [];
104
- for (const header of originalHeaders) {
105
- const headerLower = header.toLowerCase();
106
- // Skip key column and non-locale headers
107
- if (headerLower === keyColumn.toLowerCase()) {
108
- continue;
109
- }
110
- // Check if this looks like a locale
111
- const isLocale = /^[a-z]{2}([_-][a-z]{2})?([_-][a-z]+)?$/.test(headerLower);
112
- if (!isLocale) {
113
- continue;
114
- }
115
- const normalized = normalizeLocaleCode(headerLower);
116
- localeMapping[normalized] = header; // Store original case
117
- originalMapping[headerLower] = normalized;
118
- normalizedLocales.push(normalized);
119
- }
120
- return {
121
- normalizedLocales: [...new Set(normalizedLocales)], // Remove duplicates
122
- localeMapping, // normalized -> original header
123
- originalMapping // original header (lowercase) -> normalized
124
- };
125
- }
126
- /**
127
- * Finds the original header name for a given normalized locale.
128
- *
129
- * Lookup order (most-specific → most-lenient):
130
- * 1. Direct key match (`'en-us'` → `'en-US'`)
131
- * 2. Lowercase key match (`'EN-US'` → key `'en-us'`)
132
- * 3. Case-insensitive key comparison
133
- * 4. Language-family prefix match – e.g. `'en'` or `'en-GB'` finds `'en-US'`
134
- * when `'en-US'` is the only English variant present in the mapping.
135
- *
136
- * @param normalizedLocale The normalized locale code (e.g., `'en-GB'`, `'en'`)
137
- * @param localeMapping Mapping from normalized locales to original headers
138
- * @returns Original header name or undefined if not found
139
- */
140
- function getOriginalHeaderForLocale(normalizedLocale, localeMapping) {
141
- // Try direct lookup first
142
- let result = localeMapping[normalizedLocale];
143
- if (result)
144
- return result;
145
- // Try lowercase lookup if direct lookup fails
146
- const lowercaseLocale = normalizedLocale.toLowerCase();
147
- result = localeMapping[lowercaseLocale];
148
- if (result)
149
- return result;
150
- // Try finding by case-insensitive key comparison
151
- for (const [key, value] of Object.entries(localeMapping)) {
152
- if (key.toLowerCase() === lowercaseLocale) {
153
- return value;
154
- }
155
- }
156
- // Language-family fallback: 'en' or 'en-GB' should find 'en-US' when that
157
- // is the only English variant present in the localeMapping.
158
- const inputLangCode = getLanguagePrefix(normalizedLocale);
159
- for (const [key, value] of Object.entries(localeMapping)) {
160
- if (getLanguagePrefix(key) === inputLangCode) {
161
- return value;
162
- }
163
- }
164
- return undefined;
165
- }
166
- /**
167
- * Finds the normalized locale for a given original header
168
- * @public
169
- * @param originalHeader The original header name (e.g., 'pl')
170
- * @param originalMapping Mapping from original headers to normalized locales
171
- * @returns Normalized locale code or undefined if not found
172
- */
173
- function getNormalizedLocaleForHeader(originalHeader, originalMapping) {
174
- return originalMapping[originalHeader.toLowerCase()];
175
- }
176
- //# sourceMappingURL=localeNormalizer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localeNormalizer.js","sourceRoot":"","sources":["../../src/utils/localeNormalizer.ts"],"names":[],"mappings":"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"}
@@ -1,109 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.readPublicSheet = readPublicSheet;
7
- const node_https_1 = __importDefault(require("node:https"));
8
- const node_http_1 = __importDefault(require("node:http"));
9
- /**
10
- * Fetches the raw response body from a URL using the built-in http/https module.
11
- * Follows a single redirect if the server issues one (3xx).
12
- */
13
- function fetchUrl(url) {
14
- return new Promise((resolve, reject) => {
15
- const client = url.startsWith("https") ? node_https_1.default : node_http_1.default;
16
- const req = client.get(url, (res) => {
17
- // Follow one redirect (e.g. Google auth redirect)
18
- if (res.statusCode !== undefined &&
19
- res.statusCode >= 300 &&
20
- res.statusCode < 400 &&
21
- res.headers.location) {
22
- fetchUrl(res.headers.location).then(resolve).catch(reject);
23
- return;
24
- }
25
- if (res.statusCode !== undefined && res.statusCode >= 400) {
26
- reject(new Error(`HTTP ${res.statusCode} while fetching ${url}`));
27
- return;
28
- }
29
- let data = "";
30
- res.on("data", (chunk) => {
31
- data += chunk.toString();
32
- });
33
- res.on("end", () => resolve(data));
34
- res.on("error", reject);
35
- });
36
- req.on("error", reject);
37
- req.end();
38
- });
39
- }
40
- /**
41
- * Strips the JSONP wrapper that the Google Visualization API adds and parses
42
- * the inner JSON object.
43
- *
44
- * Expected wrapper format:
45
- * `/*O_o*\/\ngoogle.visualization.Query.setResponse({...});`
46
- */
47
- function parseGvizResponse(raw) {
48
- const match = raw.match(/google\.visualization\.Query\.setResponse\((\{[\s\S]*?\})\)/);
49
- if (!match) {
50
- throw new Error('Unexpected response format from Google Visualization API. ' +
51
- 'Make sure the spreadsheet is shared as "Anyone with link can view".');
52
- }
53
- return JSON.parse(match[1]);
54
- }
55
- /**
56
- * Reads rows from a *publicly accessible* Google Spreadsheet sheet without
57
- * requiring any service-account credentials or API key.
58
- *
59
- * The spreadsheet must be shared with **"Anyone with link can view"** (or
60
- * broader). Works via Google's Visualization (gviz) query endpoint which
61
- * is available at no cost for public sheets.
62
- *
63
- * @param spreadsheetId - The Google Spreadsheet ID (from the URL)
64
- * @param sheetName - The sheet tab name to fetch
65
- * @returns An array of row objects keyed by column header
66
- * @throws If the sheet is not accessible or the response cannot be parsed
67
- */
68
- async function readPublicSheet(spreadsheetId, sheetName) {
69
- // `headers=1` tells the gviz API to treat the first spreadsheet row as column
70
- // labels (col.label). Without it Google may return empty labels and fall back
71
- // to column IDs (A, B, C …) which are not valid locale codes.
72
- const url = `https://docs.google.com/spreadsheets/d/${encodeURIComponent(spreadsheetId)}` +
73
- `/gviz/tq?tqx=out:json&headers=1&sheet=${encodeURIComponent(sheetName)}`;
74
- let raw;
75
- try {
76
- raw = await fetchUrl(url);
77
- }
78
- catch (err) {
79
- throw new Error(`Failed to fetch public sheet "${sheetName}" from spreadsheet "${spreadsheetId}"`, { cause: err });
80
- }
81
- let data;
82
- try {
83
- data = parseGvizResponse(raw);
84
- }
85
- catch (err) {
86
- throw new Error(`Failed to parse response for sheet "${sheetName}" in spreadsheet "${spreadsheetId}"`, { cause: err });
87
- }
88
- if (data.status !== "ok") {
89
- const message = data.errors?.[0]?.message ?? "Unknown error";
90
- throw new Error(`Google Visualization API returned an error for sheet "${sheetName}": ${message}`);
91
- }
92
- if (!data.table) {
93
- return [];
94
- }
95
- const { cols, rows } = data.table;
96
- const headers = cols.map((col) => col.label || col.id);
97
- return rows
98
- .filter((row) => row && row.c)
99
- .map((row) => {
100
- const obj = {};
101
- for (let i = 0; i < headers.length; i++) {
102
- const cell = row.c?.[i];
103
- obj[headers[i]] = cell?.v != null ? String(cell.v) : "";
104
- }
105
- return obj;
106
- });
107
- }
108
- exports.default = readPublicSheet;
109
- //# sourceMappingURL=publicSheetReader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"publicSheetReader.js","sourceRoot":"","sources":["../../src/utils/publicSheetReader.ts"],"names":[],"mappings":";;;;;AAgGA,0CAuDC;AAvJD,4DAA+B;AAC/B,0DAA6B;AA4B7B;;;GAGG;AACH,SAAS,QAAQ,CAAC,GAAW;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAK,CAAC,CAAC,CAAC,mBAAI,CAAC;QACtD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,kDAAkD;YAClD,IACC,GAAG,CAAC,UAAU,KAAK,SAAS;gBAC5B,GAAG,CAAC,UAAU,IAAI,GAAG;gBACrB,GAAG,CAAC,UAAU,GAAG,GAAG;gBACpB,GAAG,CAAC,OAAO,CAAC,QAAQ,EACnB,CAAC;gBACF,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC3D,OAAO;YACR,CAAC;YAED,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBAC3D,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,UAAU,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC;gBAClE,OAAO;YACR,CAAC;YAED,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBAChC,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,GAAG,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACvF,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACd,4DAA4D;YAC3D,qEAAqE,CACtE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAiB,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,eAAe,CACpC,aAAqB,EACrB,SAAiB;IAEjB,8EAA8E;IAC9E,8EAA8E;IAC9E,8DAA8D;IAC9D,MAAM,GAAG,GACR,0CAA0C,kBAAkB,CAAC,aAAa,CAAC,EAAE;QAC7E,yCAAyC,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IAE1E,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACJ,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACd,iCAAiC,SAAS,uBAAuB,aAAa,GAAG,EACjF,EAAE,KAAK,EAAE,GAAG,EAAE,CACd,CAAC;IACH,CAAC;IAED,IAAI,IAAkB,CAAC;IACvB,IAAI,CAAC;QACJ,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACd,uCAAuC,SAAS,qBAAqB,aAAa,GAAG,EACrF,EAAE,KAAK,EAAE,GAAG,EAAE,CACd,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,eAAe,CAAC;QAC7D,MAAM,IAAI,KAAK,CACd,yDAAyD,SAAS,MAAM,OAAO,EAAE,CACjF,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;IAEvD,OAAO,IAAI;SACT,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;SAC7B,GAAG,CAAC,CAAC,GAAG,EAAY,EAAE;QACtB,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kBAAe,eAAe,CAAC"}