@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.
- package/README.md +58 -55
- package/dist/action-entrypoint.d.ts +2 -0
- package/dist/action-entrypoint.d.ts.map +1 -0
- package/dist/esm/index.js +1226 -0
- package/dist/esm/package.json +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1288 -41
- package/dist/utils/dataConverter/findLocalChanges.d.ts +2 -1
- package/dist/utils/dataConverter/findLocalChanges.d.ts.map +1 -1
- package/dist/utils/localeNormalizer.d.ts +31 -0
- package/dist/utils/localeNormalizer.d.ts.map +1 -1
- package/dist/utils/translationHelpers.d.ts +107 -0
- package/dist/utils/translationHelpers.d.ts.map +1 -0
- package/package.json +21 -14
- package/dist/constants.js +0 -9
- package/dist/constants.js.map +0 -1
- package/dist/getSpreadSheetData.js +0 -170
- package/dist/getSpreadSheetData.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/utils/auth.js +0 -23
- package/dist/utils/auth.js.map +0 -1
- package/dist/utils/configurationHandler.js +0 -29
- package/dist/utils/configurationHandler.js.map +0 -1
- package/dist/utils/dataConverter/convertFromDataJsonFormat.js +0 -47
- package/dist/utils/dataConverter/convertFromDataJsonFormat.js.map +0 -1
- package/dist/utils/dataConverter/convertToDataJsonFormat.js +0 -51
- package/dist/utils/dataConverter/convertToDataJsonFormat.js.map +0 -1
- package/dist/utils/dataConverter/findLocalChanges.js +0 -70
- package/dist/utils/dataConverter/findLocalChanges.js.map +0 -1
- package/dist/utils/fileWriter.js +0 -119
- package/dist/utils/fileWriter.js.map +0 -1
- package/dist/utils/getFileLastModified.js +0 -23
- package/dist/utils/getFileLastModified.js.map +0 -1
- package/dist/utils/isDataJsonNewer.js +0 -40
- package/dist/utils/isDataJsonNewer.js.map +0 -1
- package/dist/utils/localeFilter.js +0 -49
- package/dist/utils/localeFilter.js.map +0 -1
- package/dist/utils/localeNormalizer.js +0 -176
- package/dist/utils/localeNormalizer.js.map +0 -1
- package/dist/utils/publicSheetReader.js +0 -109
- package/dist/utils/publicSheetReader.js.map +0 -1
- package/dist/utils/rateLimiter.js +0 -55
- package/dist/utils/rateLimiter.js.map +0 -1
- package/dist/utils/readDataJson.js +0 -29
- package/dist/utils/readDataJson.js.map +0 -1
- package/dist/utils/sheetProcessor.js +0 -121
- package/dist/utils/sheetProcessor.js.map +0 -1
- package/dist/utils/spreadsheetCreator.js +0 -121
- package/dist/utils/spreadsheetCreator.js.map +0 -1
- package/dist/utils/spreadsheetUpdater.js +0 -227
- package/dist/utils/spreadsheetUpdater.js.map +0 -1
- package/dist/utils/syncManager.js +0 -62
- package/dist/utils/syncManager.js.map +0 -1
- package/dist/utils/validateEnv.js +0 -41
- package/dist/utils/validateEnv.js.map +0 -1
- package/dist/utils/wait.js +0 -19
- package/dist/utils/wait.js.map +0 -1
|
@@ -7,7 +7,8 @@ import type { TranslationData } from "../../types";
|
|
|
7
7
|
* - The sheet or key is absent for the resolved locale.
|
|
8
8
|
*
|
|
9
9
|
* Locale matching is fuzzy: `'en'` and `'en-GB'` will both match against
|
|
10
|
-
* an `'en-us'` entry in `spreadsheetData` (language-family resolution
|
|
10
|
+
* an `'en-us'` entry in `spreadsheetData` (language-family resolution via
|
|
11
|
+
* `resolveLocaleWithFallback`).
|
|
11
12
|
*
|
|
12
13
|
* @param localData - Data from local languageData.json file
|
|
13
14
|
* @param spreadsheetData - Data fetched from the spreadsheet
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findLocalChanges.d.ts","sourceRoot":"","sources":["../../../src/utils/dataConverter/findLocalChanges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"findLocalChanges.d.ts","sourceRoot":"","sources":["../../../src/utils/dataConverter/findLocalChanges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC/B,SAAS,EAAE,eAAe,EAC1B,eAAe,EAAE,eAAe,GAC9B,eAAe,CAgCjB"}
|
|
@@ -54,4 +54,35 @@ export declare function getOriginalHeaderForLocale(normalizedLocale: string, loc
|
|
|
54
54
|
* @returns Normalized locale code or undefined if not found
|
|
55
55
|
*/
|
|
56
56
|
export declare function getNormalizedLocaleForHeader(originalHeader: string, originalMapping: Record<string, string>): string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Resolves a locale code to the closest matching locale in an available list
|
|
59
|
+
* using a three-step fallback strategy:
|
|
60
|
+
*
|
|
61
|
+
* 1. **Exact match** — `'en-us'` → `'en-us'`
|
|
62
|
+
* 2. **Lowercase match** — `'en-US'` → `'en-us'`
|
|
63
|
+
* 3. **Language-family prefix** — `'en'` or `'en-GB'` → `'en-us'`
|
|
64
|
+
* when `'en-us'` is the only English variant in `availableLocales`
|
|
65
|
+
*
|
|
66
|
+
* Returns `undefined` when no matching locale is found.
|
|
67
|
+
*
|
|
68
|
+
* This is the same strategy used internally by `findLocalChanges()` when
|
|
69
|
+
* mapping local `languageData.json` keys to spreadsheet locale columns.
|
|
70
|
+
*
|
|
71
|
+
* @param locale - The locale code to resolve (e.g. `'en'`, `'en-GB'`).
|
|
72
|
+
* @param availableLocales - Array of locale codes to search (e.g. from
|
|
73
|
+
* `Object.keys(translations)` or the `locales` array from `getSpreadSheetData`).
|
|
74
|
+
* @returns The matched locale code from `availableLocales`, or `undefined`.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* import { resolveLocaleWithFallback } from '@el-j/google-sheet-translations';
|
|
79
|
+
*
|
|
80
|
+
* const locales = ['en-us', 'de-de', 'fr-fr'];
|
|
81
|
+
* resolveLocaleWithFallback('en', locales); // → 'en-us'
|
|
82
|
+
* resolveLocaleWithFallback('en-GB', locales); // → 'en-us'
|
|
83
|
+
* resolveLocaleWithFallback('de-DE', locales); // → 'de-de'
|
|
84
|
+
* resolveLocaleWithFallback('ja', locales); // → undefined
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveLocaleWithFallback(locale: string, availableLocales: string[]): string | undefined;
|
|
57
88
|
//# sourceMappingURL=localeNormalizer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localeNormalizer.d.ts","sourceRoot":"","sources":["../../src/utils/localeNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AA4CD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0B1D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,eAAe,EAAE,MAAM,EAAE,EACzB,SAAS,EAAE,MAAM,GACf;IACF,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CA+BA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACzC,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,MAAM,GAAG,SAAS,CA2BpB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC3C,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,MAAM,GAAG,SAAS,CAEpB"}
|
|
1
|
+
{"version":3,"file":"localeNormalizer.d.ts","sourceRoot":"","sources":["../../src/utils/localeNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AA4CD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0B1D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,eAAe,EAAE,MAAM,EAAE,EACzB,SAAS,EAAE,MAAM,GACf;IACF,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CA+BA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACzC,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,MAAM,GAAG,SAAS,CA2BpB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC3C,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EAAE,GACxB,MAAM,GAAG,SAAS,CAUpB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Higher-level translation utility helpers.
|
|
3
|
+
*
|
|
4
|
+
* These utilities solve common patterns that appear when consuming the
|
|
5
|
+
* translation data returned by `getSpreadSheetData()`. They were previously
|
|
6
|
+
* implemented inline in the documentation website; extracting them into the
|
|
7
|
+
* package makes them reusable for every downstream consumer.
|
|
8
|
+
*/
|
|
9
|
+
import type { TranslationData, TranslationValue } from '../types';
|
|
10
|
+
/**
|
|
11
|
+
* Per-sheet summary for a single locale: sheet name and the number of
|
|
12
|
+
* translation keys it contains.
|
|
13
|
+
*/
|
|
14
|
+
export interface SheetSummary {
|
|
15
|
+
sheet: string;
|
|
16
|
+
count: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Translation summary keyed by locale.
|
|
20
|
+
* Each locale maps to an array of sheet summaries with key counts.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const summary = getTranslationSummary(translations);
|
|
25
|
+
* // { 'en-us': [{ sheet: 'landingPage', count: 12 }, { sheet: 'ui', count: 5 }], ... }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type TranslationSummary = Record<string, SheetSummary[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Builds a summary of translation key counts per locale and sheet.
|
|
31
|
+
*
|
|
32
|
+
* Useful for dashboards, translation coverage reports, and monitoring.
|
|
33
|
+
*
|
|
34
|
+
* @param translations - The `TranslationData` object returned by
|
|
35
|
+
* `getSpreadSheetData()`.
|
|
36
|
+
* @returns A `TranslationSummary` mapping each locale to an array of
|
|
37
|
+
* `{ sheet, count }` entries.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import { getSpreadSheetData, getTranslationSummary } from '@el-j/google-sheet-translations';
|
|
42
|
+
*
|
|
43
|
+
* const translations = await getSpreadSheetData(['ui', 'landingPage'], { publicSheet: true, spreadsheetId: '...' });
|
|
44
|
+
* const summary = getTranslationSummary(translations);
|
|
45
|
+
* // summary['en-us'] = [{ sheet: 'ui', count: 5 }, { sheet: 'landingPage', count: 12 }]
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function getTranslationSummary(translations: TranslationData): TranslationSummary;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the human-readable display name for a locale by looking it up in
|
|
51
|
+
* the `i18n` sheet of the translation data.
|
|
52
|
+
*
|
|
53
|
+
* The `i18n` sheet is expected to follow the convention used by the demo
|
|
54
|
+
* spreadsheet: translation keys are locale codes (e.g. `"en-us"`,
|
|
55
|
+
* `"de-de"`) and their values are the locale's own name in that language —
|
|
56
|
+
* i.e. the mapping is self-referential. For example:
|
|
57
|
+
* - locale `"en-us"` → key `"en-us"` in the `"i18n"` sheet → `"English"`
|
|
58
|
+
* - locale `"de-de"` → key `"de-de"` in the `"i18n"` sheet → `"Deutsch"`
|
|
59
|
+
*
|
|
60
|
+
* Falls back to the raw locale code if the name is not found.
|
|
61
|
+
*
|
|
62
|
+
* @param locale - The locale code to look up (e.g. `"de-de"`).
|
|
63
|
+
* @param translations - The `TranslationData` object returned by
|
|
64
|
+
* `getSpreadSheetData()`.
|
|
65
|
+
* @param i18nSheet - The sheet that contains locale display names
|
|
66
|
+
* (default: `"i18n"`).
|
|
67
|
+
* @returns Human-readable locale name, or `locale` itself as a fallback.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { getSpreadSheetData, getLocaleDisplayName } from '@el-j/google-sheet-translations';
|
|
72
|
+
*
|
|
73
|
+
* const translations = await getSpreadSheetData(['i18n'], { publicSheet: true, spreadsheetId: '...' });
|
|
74
|
+
* const name = getLocaleDisplayName('de-de', translations);
|
|
75
|
+
* // → 'Deutsch'
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function getLocaleDisplayName(locale: string, translations: TranslationData, i18nSheet?: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* Selects one or more sheets from the translation data for a given locale and
|
|
81
|
+
* merges them into a single flat key→value map.
|
|
82
|
+
*
|
|
83
|
+
* Later sheets in `sheetNames` overwrite earlier ones when there are duplicate
|
|
84
|
+
* keys (same semantics as `Object.assign`).
|
|
85
|
+
*
|
|
86
|
+
* This is the canonical way to extract a "current locale" translation map for
|
|
87
|
+
* rendering UI strings when translation keys are spread across multiple sheets.
|
|
88
|
+
*
|
|
89
|
+
* @param translations - The `TranslationData` object returned by
|
|
90
|
+
* `getSpreadSheetData()`.
|
|
91
|
+
* @param locale - The locale whose data should be extracted.
|
|
92
|
+
* @param sheetNames - Which sheets to merge (in order). Omit to merge all
|
|
93
|
+
* sheets for the locale.
|
|
94
|
+
* @returns Flat `{ key: value }` map. Returns an empty object if the locale
|
|
95
|
+
* or none of the requested sheets are found.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { getSpreadSheetData, mergeSheets } from '@el-j/google-sheet-translations';
|
|
100
|
+
*
|
|
101
|
+
* const translations = await getSpreadSheetData(['ui', 'landingPage'], { publicSheet: true, spreadsheetId: '...' });
|
|
102
|
+
* const t = mergeSheets(translations, 'de-de', ['ui', 'landingPage']);
|
|
103
|
+
* // t.hero_title === 'Willkommen'
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function mergeSheets(translations: TranslationData, locale: string, sheetNames?: string[]): Record<string, TranslationValue>;
|
|
107
|
+
//# sourceMappingURL=translationHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translationHelpers.d.ts","sourceRoot":"","sources":["../../src/utils/translationHelpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAMlE;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;AAMhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,eAAe,GAAG,kBAAkB,CASvF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,eAAe,EAC7B,SAAS,SAAS,GAChB,MAAM,CAUR;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAC1B,YAAY,EAAE,eAAe,EAC7B,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EAAE,GACnB,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAalC"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@el-j/google-sheet-translations",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A package to manage translations stored in Google Spreadsheets",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
9
10
|
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/esm/index.js",
|
|
10
12
|
"require": "./dist/index.js",
|
|
11
|
-
"import": "./dist/index.js",
|
|
12
13
|
"default": "./dist/index.js"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
@@ -21,7 +22,11 @@
|
|
|
21
22
|
"README.md"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
24
|
-
"build": "
|
|
25
|
+
"build:action": "rimraf dist-action && esbuild src/action-entrypoint.ts --bundle --platform=node --format=esm --outfile=dist-action/index.mjs --banner:js=\"import{createRequire}from'module';const require=createRequire(import.meta.url);\" --log-level=info",
|
|
26
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
27
|
+
"build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=dist/index.js --platform=node --packages=external",
|
|
28
|
+
"build:esm": "esbuild src/index.ts --bundle --format=esm --outfile=dist/esm/index.js --platform=node --packages=external && node -e \"require('fs').writeFileSync('dist/esm/package.json', JSON.stringify({type:'module'}))\"",
|
|
29
|
+
"build": "npm run build:types && npm run build:cjs && npm run build:esm",
|
|
25
30
|
"clean": "rimraf dist",
|
|
26
31
|
"prebuild": "npm run clean",
|
|
27
32
|
"prepare": "npm run build",
|
|
@@ -54,8 +59,9 @@
|
|
|
54
59
|
"author": "el-j",
|
|
55
60
|
"license": "MIT",
|
|
56
61
|
"dependencies": {
|
|
57
|
-
"
|
|
58
|
-
"google-
|
|
62
|
+
"@actions/core": "^3.0.0",
|
|
63
|
+
"google-auth-library": "^10.6.1",
|
|
64
|
+
"google-spreadsheet": "^5.2.0"
|
|
59
65
|
},
|
|
60
66
|
"peerDependencies": {
|
|
61
67
|
"typescript": ">=4.0.0"
|
|
@@ -69,19 +75,20 @@
|
|
|
69
75
|
"@semantic-release/npm": "^13.1.5",
|
|
70
76
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
71
77
|
"@types/jest": "^30.0.0",
|
|
72
|
-
"@types/node": "^
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
74
|
-
"@typescript-eslint/parser": "^8.
|
|
78
|
+
"@types/node": "^25.4.0",
|
|
79
|
+
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
|
80
|
+
"@typescript-eslint/parser": "^8.57.0",
|
|
81
|
+
"esbuild": "^0.26.0",
|
|
75
82
|
"conventional-changelog-conventionalcommits": "^9.3.0",
|
|
76
|
-
"dotenv": "17.
|
|
83
|
+
"dotenv": "17.3.1",
|
|
77
84
|
"eslint": "^10.0.3",
|
|
78
|
-
"jest": "^30.0
|
|
85
|
+
"jest": "^30.3.0",
|
|
79
86
|
"jest-mock-extended": "^4.0.0",
|
|
80
|
-
"rimraf": "^6.
|
|
87
|
+
"rimraf": "^6.1.3",
|
|
81
88
|
"semantic-release": "^25.0.3",
|
|
82
|
-
"ts-jest": "^29.4.
|
|
89
|
+
"ts-jest": "^29.4.6",
|
|
83
90
|
"ts-node": "^10.9.2",
|
|
84
|
-
"typescript": "^5.
|
|
91
|
+
"typescript": "^5.9.3",
|
|
85
92
|
"vitepress": "^1.6.4"
|
|
86
93
|
},
|
|
87
94
|
"engines": {
|
|
@@ -89,7 +96,7 @@
|
|
|
89
96
|
},
|
|
90
97
|
"overrides": {
|
|
91
98
|
"google-spreadsheet": {
|
|
92
|
-
"google-auth-library": "^10.1
|
|
99
|
+
"google-auth-library": "^10.6.1"
|
|
93
100
|
}
|
|
94
101
|
}
|
|
95
102
|
}
|
package/dist/constants.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Package-wide constants
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DEFAULT_WAIT_SECONDS = void 0;
|
|
7
|
-
/** Default wait time between Google Sheets API calls (in seconds) */
|
|
8
|
-
exports.DEFAULT_WAIT_SECONDS = 1;
|
|
9
|
-
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,qEAAqE;AACxD,QAAA,oBAAoB,GAAG,CAAC,CAAC"}
|
|
@@ -1,170 +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.DEFAULT_WAIT_SECONDS = void 0;
|
|
7
|
-
exports.getSpreadSheetData = getSpreadSheetData;
|
|
8
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
const google_spreadsheet_1 = require("google-spreadsheet");
|
|
11
|
-
const auth_1 = require("./utils/auth");
|
|
12
|
-
const configurationHandler_1 = require("./utils/configurationHandler");
|
|
13
|
-
const sheetProcessor_1 = require("./utils/sheetProcessor");
|
|
14
|
-
const fileWriter_1 = require("./utils/fileWriter");
|
|
15
|
-
const syncManager_1 = require("./utils/syncManager");
|
|
16
|
-
const rateLimiter_1 = require("./utils/rateLimiter");
|
|
17
|
-
const publicSheetReader_1 = require("./utils/publicSheetReader");
|
|
18
|
-
const spreadsheetCreator_1 = require("./utils/spreadsheetCreator");
|
|
19
|
-
const constants_1 = require("./constants");
|
|
20
|
-
Object.defineProperty(exports, "DEFAULT_WAIT_SECONDS", { enumerable: true, get: function () { return constants_1.DEFAULT_WAIT_SECONDS; } });
|
|
21
|
-
/**
|
|
22
|
-
* Fetches and processes data from a Google Spreadsheet.
|
|
23
|
-
*
|
|
24
|
-
* Modes:
|
|
25
|
-
* - **Authenticated** (default): uses a Google Cloud service account.
|
|
26
|
-
* Supports bidirectional sync, auto-translate, and auto-create.
|
|
27
|
-
* - **Public** (`publicSheet: true`): reads via the Google Visualization API
|
|
28
|
-
* with no credentials. The spreadsheet must be shared publicly.
|
|
29
|
-
*
|
|
30
|
-
* **Auto-create**: when no spreadsheet ID is available and `autoCreate` is true
|
|
31
|
-
* (the default), a new spreadsheet is created automatically on first run.
|
|
32
|
-
*/
|
|
33
|
-
const MAX_SYNC_REFRESH_DEPTH = 1;
|
|
34
|
-
/** Appends (or updates) GOOGLE_SPREADSHEET_ID in .env when the file exists. */
|
|
35
|
-
async function persistSpreadsheetId(id) {
|
|
36
|
-
const envPath = node_path_1.default.join(process.cwd(), '.env');
|
|
37
|
-
try {
|
|
38
|
-
let content = '';
|
|
39
|
-
if (node_fs_1.default.existsSync(envPath)) {
|
|
40
|
-
content = node_fs_1.default.readFileSync(envPath, 'utf8');
|
|
41
|
-
if (/^GOOGLE_SPREADSHEET_ID=/m.test(content)) {
|
|
42
|
-
content = content.replace(/^GOOGLE_SPREADSHEET_ID=.*/m, `GOOGLE_SPREADSHEET_ID=${id}`);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
content = content.trimEnd() + `\nGOOGLE_SPREADSHEET_ID=${id}\n`;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
content = `GOOGLE_SPREADSHEET_ID=${id}\n`;
|
|
50
|
-
}
|
|
51
|
-
node_fs_1.default.writeFileSync(envPath, content, 'utf8');
|
|
52
|
-
console.log(` Saved GOOGLE_SPREADSHEET_ID to ${envPath}`);
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
console.warn(` Could not write .env: ${err.message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
|
|
59
|
-
const config = (0, configurationHandler_1.normalizeConfig)(options);
|
|
60
|
-
const baseDelayMs = config.waitSeconds * 1000;
|
|
61
|
-
const docTitle = _docTitle ?? [];
|
|
62
|
-
if (docTitle.length === 0) {
|
|
63
|
-
console.warn("No sheet titles provided, cannot process spreadsheet data");
|
|
64
|
-
return {};
|
|
65
|
-
}
|
|
66
|
-
if (!docTitle.includes("i18n")) {
|
|
67
|
-
docTitle.push("i18n");
|
|
68
|
-
}
|
|
69
|
-
const finalTranslations = {};
|
|
70
|
-
const allLocales = new Set();
|
|
71
|
-
const localesWithContent = new Set();
|
|
72
|
-
const globalLocaleMapping = {};
|
|
73
|
-
const globalOriginalMapping = {};
|
|
74
|
-
function mergeResult(result, title) {
|
|
75
|
-
if (!result.success)
|
|
76
|
-
return;
|
|
77
|
-
for (const [normalized, original] of Object.entries(result.localeMapping)) {
|
|
78
|
-
if (!globalLocaleMapping[normalized])
|
|
79
|
-
globalLocaleMapping[normalized] = original;
|
|
80
|
-
}
|
|
81
|
-
for (const [original, normalized] of Object.entries(result.originalMapping)) {
|
|
82
|
-
if (!globalOriginalMapping[original])
|
|
83
|
-
globalOriginalMapping[original] = normalized;
|
|
84
|
-
}
|
|
85
|
-
for (const locale of result.locales) {
|
|
86
|
-
if (finalTranslations[locale]) {
|
|
87
|
-
finalTranslations[locale] = { ...finalTranslations[locale], ...result.translations[locale] };
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
finalTranslations[locale] = result.translations[locale];
|
|
91
|
-
}
|
|
92
|
-
allLocales.add(locale);
|
|
93
|
-
if (title !== "i18n" && result.translations[locale]) {
|
|
94
|
-
const hasActualTranslations = Object.values(result.translations[locale]).some((sheetTranslations) => Object.keys(sheetTranslations).length > 0);
|
|
95
|
-
if (hasActualTranslations)
|
|
96
|
-
localesWithContent.add(locale);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (config.publicSheet) {
|
|
101
|
-
// ── Public (unauthenticated) path ──────────────────────────────────────
|
|
102
|
-
const spreadsheetId = config.spreadsheetId ?? process.env.GOOGLE_SPREADSHEET_ID;
|
|
103
|
-
if (!spreadsheetId) {
|
|
104
|
-
throw new Error("No spreadsheet ID provided. Set GOOGLE_SPREADSHEET_ID or pass spreadsheetId in options.");
|
|
105
|
-
}
|
|
106
|
-
console.log(`Processing ${docTitle.length} sheets: ${docTitle.join(", ")}`);
|
|
107
|
-
await Promise.all(docTitle.map(async (title) => {
|
|
108
|
-
let rows;
|
|
109
|
-
try {
|
|
110
|
-
rows = await (0, rateLimiter_1.withRetry)(() => (0, publicSheetReader_1.readPublicSheet)(spreadsheetId, title), `readPublicSheet: ${title}`, baseDelayMs);
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
console.warn(`Sheet "${title}" could not be fetched: ${err.message}`);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
mergeResult(await (0, sheetProcessor_1.processRawRows)(rows, title), title);
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
// ── Authenticated path ─────────────────────────────────────────────────
|
|
121
|
-
const serviceAuthClient = (0, auth_1.createAuthClient)();
|
|
122
|
-
// Resolve spreadsheet ID: option > env var > auto-create
|
|
123
|
-
let spreadsheetId = config.spreadsheetId ?? process.env.GOOGLE_SPREADSHEET_ID;
|
|
124
|
-
if (!spreadsheetId) {
|
|
125
|
-
if (config.autoCreate) {
|
|
126
|
-
const created = await (0, spreadsheetCreator_1.createSpreadsheet)(serviceAuthClient, {
|
|
127
|
-
title: config.spreadsheetTitle,
|
|
128
|
-
sourceLocale: config.sourceLocale,
|
|
129
|
-
targetLocales: config.targetLocales,
|
|
130
|
-
});
|
|
131
|
-
spreadsheetId = created.spreadsheetId;
|
|
132
|
-
await persistSpreadsheetId(spreadsheetId);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
throw new Error("No spreadsheet ID provided. Set GOOGLE_SPREADSHEET_ID or pass spreadsheetId in options.");
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
console.log(`Processing ${docTitle.length} sheets: ${docTitle.join(", ")}`);
|
|
139
|
-
const doc = new google_spreadsheet_1.GoogleSpreadsheet(spreadsheetId, serviceAuthClient);
|
|
140
|
-
try {
|
|
141
|
-
await (0, rateLimiter_1.withRetry)(() => doc.loadInfo(true), "loadInfo", baseDelayMs);
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
throw new Error(`Failed to load spreadsheet "${spreadsheetId}"`, { cause: err });
|
|
145
|
-
}
|
|
146
|
-
await Promise.all(docTitle.map(async (title) => {
|
|
147
|
-
const sheet = doc.sheetsByTitle[title];
|
|
148
|
-
if (!sheet) {
|
|
149
|
-
console.warn(`Sheet "${title}" not found in the document`);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
mergeResult(await (0, sheetProcessor_1.processSheet)(sheet, title, config.rowLimit, baseDelayMs), title);
|
|
153
|
-
}));
|
|
154
|
-
const syncResult = await (0, syncManager_1.handleBidirectionalSync)(doc, config.dataJsonPath, config.translationsOutputDir, config.syncLocalChanges, config.autoTranslate, finalTranslations, config.waitSeconds, globalLocaleMapping);
|
|
155
|
-
if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
|
|
156
|
-
return getSpreadSheetData(_docTitle, { ...options, syncLocalChanges: false }, _refreshDepth + 1);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
const localesForOutput = localesWithContent.size > 0 ? Array.from(localesWithContent) : Array.from(allLocales);
|
|
160
|
-
const allLocalesArray = Array.from(allLocales);
|
|
161
|
-
(0, fileWriter_1.writeTranslationFiles)(finalTranslations, allLocalesArray, config.translationsOutputDir);
|
|
162
|
-
(0, fileWriter_1.writeLocalesFile)(localesForOutput, globalLocaleMapping, config.localesOutputPath);
|
|
163
|
-
console.log(`Writing locales file with ${localesForOutput.length} locales that have actual translations:`, localesForOutput);
|
|
164
|
-
if (Object.keys(finalTranslations).length > 0) {
|
|
165
|
-
(0, fileWriter_1.writeLanguageDataFile)(finalTranslations, allLocalesArray, config.dataJsonPath);
|
|
166
|
-
}
|
|
167
|
-
return finalTranslations;
|
|
168
|
-
}
|
|
169
|
-
exports.default = getSpreadSheetData;
|
|
170
|
-
//# sourceMappingURL=getSpreadSheetData.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getSpreadSheetData.js","sourceRoot":"","sources":["../src/getSpreadSheetData.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mBAAmB;AACnB,2DAAgF;AAAvE,wHAAA,kBAAkB,OAAA;AAAE,0HAAA,oBAAoB,OAAA;AAKjD,2CAA2C;AAC3C,qCAAoC;AAA3B,4FAAA,IAAI,OAAA;AACb,mDAAgD;AAAvC,wGAAA,SAAS,OAAA;AAClB,mDAAkD;AAAzC,0GAAA,WAAW,OAAA;AACpB,qCAAgD;AAAvC,wGAAA,gBAAgB,OAAA;AACzB,yFAAwF;AAA/E,kIAAA,uBAAuB,OAAA;AAChC,6FAA4F;AAAnF,sIAAA,yBAAyB,OAAA;AAClC,2EAA0E;AAAjE,oHAAA,gBAAgB,OAAA;AACzB,iEAA+E;AAAtE,uIAAA,iCAAiC,OAAA;AAE1C,wCAAwC;AACxC,+DAA4D;AAAnD,oHAAA,eAAe,OAAA;AAExB,kCAAkC;AAClC,iEAA+D;AAAtD,uHAAA,iBAAiB,OAAA;AAC1B,mDAA0D;AAAjD,kHAAA,mBAAmB,OAAA;AAE5B,kDAAkD;AAClD,qDAAyE;AAAhE,6GAAA,aAAa,OAAA;AAAE,kHAAA,kBAAkB,OAAA;AAU1C,iBAAiB;AACjB,6DAA0D;AAC1D,kBAAe,uCAAkB,CAAC"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils/auth.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAuthClient = createAuthClient;
|
|
4
|
-
const google_auth_library_1 = require("google-auth-library");
|
|
5
|
-
const validateEnv_1 = require("./validateEnv");
|
|
6
|
-
/**
|
|
7
|
-
* Creates and returns a JWT auth client for Google Sheets API
|
|
8
|
-
* @returns JWT authentication client
|
|
9
|
-
*/
|
|
10
|
-
function createAuthClient() {
|
|
11
|
-
const { GOOGLE_CLIENT_EMAIL, GOOGLE_PRIVATE_KEY } = (0, validateEnv_1.validateCredentials)();
|
|
12
|
-
// GitHub Actions (and many CI systems) store secrets with literal `\n`
|
|
13
|
-
// instead of real newlines. The PEM key must have actual newlines for
|
|
14
|
-
// OpenSSL to parse it; replace any escaped sequences before use.
|
|
15
|
-
const normalizedKey = GOOGLE_PRIVATE_KEY.replace(/\\n/g, "\n");
|
|
16
|
-
return new google_auth_library_1.JWT({
|
|
17
|
-
email: GOOGLE_CLIENT_EMAIL,
|
|
18
|
-
key: normalizedKey,
|
|
19
|
-
scopes: ["https://www.googleapis.com/auth/spreadsheets"],
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
exports.default = createAuthClient;
|
|
23
|
-
//# sourceMappingURL=auth.js.map
|
package/dist/utils/auth.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":";;AAOA,4CAaC;AApBD,6DAA0C;AAC1C,+CAAoD;AAEpD;;;GAGG;AACH,SAAgB,gBAAgB;IAC/B,MAAM,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,GAAG,IAAA,iCAAmB,GAAE,CAAC;IAE1E,uEAAuE;IACvE,sEAAsE;IACtE,iEAAiE;IACjE,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE/D,OAAO,IAAI,yBAAG,CAAC;QACd,KAAK,EAAE,mBAAmB;QAC1B,GAAG,EAAE,aAAa;QAClB,MAAM,EAAE,CAAC,8CAA8C,CAAC;KACxD,CAAC,CAAC;AACJ,CAAC;AAED,kBAAe,gBAAgB,CAAC"}
|
|
@@ -1,29 +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.normalizeConfig = normalizeConfig;
|
|
7
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
-
const constants_1 = require("../constants");
|
|
9
|
-
/**
|
|
10
|
-
* Normalizes configuration options by applying defaults
|
|
11
|
-
*/
|
|
12
|
-
function normalizeConfig(options = {}) {
|
|
13
|
-
return {
|
|
14
|
-
rowLimit: options.rowLimit ?? 100,
|
|
15
|
-
waitSeconds: options.waitSeconds ?? constants_1.DEFAULT_WAIT_SECONDS,
|
|
16
|
-
dataJsonPath: options.dataJsonPath ?? node_path_1.default.join(process.cwd(), "src/lib/languageData.json"),
|
|
17
|
-
localesOutputPath: options.localesOutputPath ?? node_path_1.default.join(process.cwd(), "src/i18n/locales.ts"),
|
|
18
|
-
translationsOutputDir: options.translationsOutputDir ?? node_path_1.default.join(process.cwd(), "translations"),
|
|
19
|
-
syncLocalChanges: options.syncLocalChanges !== false, // Default to true
|
|
20
|
-
autoTranslate: options.autoTranslate === true, // Default to false
|
|
21
|
-
spreadsheetId: options.spreadsheetId,
|
|
22
|
-
publicSheet: options.publicSheet === true, // Default to false
|
|
23
|
-
autoCreate: options.autoCreate !== false, // Default to true
|
|
24
|
-
spreadsheetTitle: options.spreadsheetTitle ?? 'google-sheet-translations',
|
|
25
|
-
sourceLocale: options.sourceLocale ?? 'en',
|
|
26
|
-
targetLocales: options.targetLocales ?? ['de', 'fr', 'es', 'it', 'pt', 'ja', 'zh'],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=configurationHandler.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configurationHandler.js","sourceRoot":"","sources":["../../src/utils/configurationHandler.ts"],"names":[],"mappings":";;;;;AA4EA,0CAgBC;AA5FD,0DAA6B;AAC7B,4CAAoD;AAwEpD;;GAEG;AACH,SAAgB,eAAe,CAAC,UAA8B,EAAE;IAC/D,OAAO;QACN,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG;QACjC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,gCAAoB;QACxD,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,2BAA2B,CAAC;QAC3F,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC;QAC/F,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,IAAI,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC;QAChG,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,KAAK,KAAK,EAAE,kBAAkB;QACxE,aAAa,EAAE,OAAO,CAAC,aAAa,KAAK,IAAI,EAAE,mBAAmB;QAClE,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,WAAW,EAAE,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,mBAAmB;QAC9D,UAAU,EAAE,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,kBAAkB;QAC5D,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,2BAA2B;QACzE,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI;QAC1C,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;KAClF,CAAC;AACH,CAAC"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertFromDataJsonFormat = convertFromDataJsonFormat;
|
|
4
|
-
/**
|
|
5
|
-
* Type-guard: checks that a value has the shape of sheet data
|
|
6
|
-
* (an object mapping locale → translation record)
|
|
7
|
-
*/
|
|
8
|
-
function isSheetData(v) {
|
|
9
|
-
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Converts languageData.json format back to the translation object structure
|
|
13
|
-
* @param dataJson - Data in the languageData.json format
|
|
14
|
-
* @returns Converted data in the TranslationData format
|
|
15
|
-
*/
|
|
16
|
-
function convertFromDataJsonFormat(dataJson) {
|
|
17
|
-
const result = {};
|
|
18
|
-
for (const projectData of dataJson) {
|
|
19
|
-
for (const sheetTitle of Object.keys(projectData)) {
|
|
20
|
-
const raw = projectData[sheetTitle];
|
|
21
|
-
if (!isSheetData(raw)) {
|
|
22
|
-
console.warn(`Skipping malformed entry for sheet "${sheetTitle}"`);
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
for (const locale of Object.keys(raw)) {
|
|
26
|
-
// Initialize locale if it doesn't exist
|
|
27
|
-
if (!result[locale]) {
|
|
28
|
-
result[locale] = {};
|
|
29
|
-
}
|
|
30
|
-
// Initialize sheet if it doesn't exist
|
|
31
|
-
if (!result[locale][sheetTitle]) {
|
|
32
|
-
result[locale][sheetTitle] = {};
|
|
33
|
-
}
|
|
34
|
-
const localeData = raw[locale];
|
|
35
|
-
if (typeof localeData !== 'object' || localeData === null) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
// Add all translations
|
|
39
|
-
for (const key of Object.keys(localeData)) {
|
|
40
|
-
result[locale][sheetTitle][key] = localeData[key];
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=convertFromDataJsonFormat.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"convertFromDataJsonFormat.js","sourceRoot":"","sources":["../../../src/utils/dataConverter/convertFromDataJsonFormat.ts"],"names":[],"mappings":";;AAiBA,8DAuCC;AAtDD;;;GAGG;AACH,SAAS,WAAW,CACnB,CAAU;IAEV,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,SAAgB,yBAAyB,CACxC,QAAmC;IAEnC,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,KAAK,MAAM,WAAW,IAAI,QAAQ,EAAE,CAAC;QACpC,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACnD,MAAM,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;YAEpC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,uCAAuC,UAAU,GAAG,CAAC,CAAC;gBACnE,SAAS;YACV,CAAC;YAED,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvC,wCAAwC;gBACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACrB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBACrB,CAAC;gBAED,uCAAuC;gBACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;oBACjC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;gBACjC,CAAC;gBAED,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC/B,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;oBAC3D,SAAS;gBACV,CAAC;gBAED,uBAAuB;gBACvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;gBACnD,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertToDataJsonFormat = convertToDataJsonFormat;
|
|
4
|
-
/**
|
|
5
|
-
* Converts the translation object to the expected languageData.json format
|
|
6
|
-
* @param translationObj - The translation object with locale->sheet->key->value structure
|
|
7
|
-
* @param locales - Array of locale identifiers
|
|
8
|
-
* @returns Converted data in the format expected for languageData.json
|
|
9
|
-
*/
|
|
10
|
-
function convertToDataJsonFormat(translationObj, locales) {
|
|
11
|
-
const result = [];
|
|
12
|
-
console.log("Converting translation object to languageData.json format...");
|
|
13
|
-
// Get all sheet names from all locales to make sure we don't miss any
|
|
14
|
-
const allSheets = new Set();
|
|
15
|
-
for (const locale of Object.keys(translationObj)) {
|
|
16
|
-
if (translationObj[locale]) {
|
|
17
|
-
for (const sheet of Object.keys(translationObj[locale])) {
|
|
18
|
-
allSheets.add(sheet);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
console.log(`Found ${allSheets.size} sheets across all locales`);
|
|
23
|
-
// Process each sheet
|
|
24
|
-
for (const sheetTitle of allSheets) {
|
|
25
|
-
// Create a new project object with the sheet title as the main key
|
|
26
|
-
const projectData = {};
|
|
27
|
-
projectData[sheetTitle] = {};
|
|
28
|
-
// For each locale, add all key-value pairs
|
|
29
|
-
for (const locale of locales) {
|
|
30
|
-
if (translationObj?.[locale]?.[sheetTitle]) { // Use original locale case for lookup
|
|
31
|
-
// Create the locale object
|
|
32
|
-
projectData[sheetTitle][locale] = {};
|
|
33
|
-
// Add all translations for this locale
|
|
34
|
-
const translations = translationObj[locale][sheetTitle];
|
|
35
|
-
for (const key of Object.keys(translations)) {
|
|
36
|
-
projectData[sheetTitle][locale][key] = translations[key];
|
|
37
|
-
}
|
|
38
|
-
// Log how many translations we found for debugging
|
|
39
|
-
console.log(`Found ${Object.keys(translations).length} keys for locale ${locale} in sheet ${sheetTitle}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Only add non-empty projects
|
|
43
|
-
if (Object.keys(projectData[sheetTitle]).length > 0) {
|
|
44
|
-
result.push(projectData);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
console.log(`Created ${result.length} sheet entries for languageData.json`);
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
|
-
exports.default = convertToDataJsonFormat;
|
|
51
|
-
//# sourceMappingURL=convertToDataJsonFormat.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"convertToDataJsonFormat.js","sourceRoot":"","sources":["../../../src/utils/dataConverter/convertToDataJsonFormat.ts"],"names":[],"mappings":";;AAQA,0DA0DC;AAhED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACtC,cAA+B,EAC/B,OAAiB;IAEjB,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAE5E,sEAAsE;IACtE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAClD,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBACzD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,SAAS,CAAC,IAAI,4BAA4B,CAAC,CAAC;IAEjE,qBAAqB;IACrB,KAAK,MAAM,UAAU,IAAI,SAAS,EAAE,CAAC;QACpC,mEAAmE;QACnE,MAAM,WAAW,GAGb,EAAE,CAAC;QACP,WAAW,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAE7B,2CAA2C;QAC3C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,cAAc,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,sCAAsC;gBAEnF,2BAA2B;gBAC3B,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAErC,uCAAuC;gBACvC,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;gBACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC7C,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;gBAC1D,CAAC;gBAED,mDAAmD;gBACnD,OAAO,CAAC,GAAG,CACV,SACC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAC3B,oBAAoB,MAAM,aAAa,UAAU,EAAE,CACnD,CAAC;YACH,CAAC;QACF,CAAC;QAED,8BAA8B;QAC9B,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,sCAAsC,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AACf,CAAC;AAED,kBAAe,uBAAuB,CAAC"}
|