@el-j/google-sheet-translations 1.0.2 → 1.2.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 +129 -1
- package/dist/getSpreadSheetData.d.ts.map +1 -1
- package/dist/getSpreadSheetData.js +124 -75
- package/dist/getSpreadSheetData.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/auth.js +1 -1
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/configurationHandler.d.ts +44 -0
- package/dist/utils/configurationHandler.d.ts.map +1 -1
- package/dist/utils/configurationHandler.js +8 -2
- package/dist/utils/configurationHandler.js.map +1 -1
- package/dist/utils/publicSheetReader.d.ts +17 -0
- package/dist/utils/publicSheetReader.d.ts.map +1 -0
- package/dist/utils/publicSheetReader.js +106 -0
- package/dist/utils/publicSheetReader.js.map +1 -0
- package/dist/utils/rateLimiter.d.ts +15 -0
- package/dist/utils/rateLimiter.d.ts.map +1 -0
- package/dist/utils/rateLimiter.js +55 -0
- package/dist/utils/rateLimiter.js.map +1 -0
- package/dist/utils/sheetProcessor.d.ts +20 -6
- package/dist/utils/sheetProcessor.d.ts.map +1 -1
- package/dist/utils/sheetProcessor.js +54 -19
- package/dist/utils/sheetProcessor.js.map +1 -1
- package/dist/utils/spreadsheetCreator.d.ts +23 -0
- package/dist/utils/spreadsheetCreator.d.ts.map +1 -0
- package/dist/utils/spreadsheetCreator.js +121 -0
- package/dist/utils/spreadsheetCreator.js.map +1 -0
- package/dist/utils/spreadsheetUpdater.d.ts +1 -1
- package/dist/utils/spreadsheetUpdater.d.ts.map +1 -1
- package/dist/utils/spreadsheetUpdater.js +8 -14
- package/dist/utils/spreadsheetUpdater.js.map +1 -1
- package/dist/utils/validateEnv.d.ts +7 -3
- package/dist/utils/validateEnv.d.ts.map +1 -1
- package/dist/utils/validateEnv.js +22 -10
- package/dist/utils/validateEnv.js.map +1 -1
- package/dist/utils/wait.d.ts +5 -2
- package/dist/utils/wait.d.ts.map +1 -1
- package/dist/utils/wait.js +8 -10
- package/dist/utils/wait.js.map +1 -1
- package/package.json +92 -91
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ A Node.js package for managing translations stored in Google Sheets.
|
|
|
11
11
|
- ✅ **Modular Architecture**: Well-tested, maintainable codebase with clear separation of concerns
|
|
12
12
|
- ✅ **Next.js Integration**: Built-in support for Next.js static export workflows
|
|
13
13
|
- ✅ **Flexible Configuration**: Customizable paths, wait times, and processing options
|
|
14
|
+
- ✅ **GitHub Action**: One-step CI integration via the bundled composite action
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
@@ -94,7 +95,7 @@ Fetches and processes data from a Google Spreadsheet.
|
|
|
94
95
|
- `sheetTitles`: (Optional) Array of sheet titles to process. If not provided, only the "i18n" sheet will be processed.
|
|
95
96
|
- `options`: (Optional) Configuration object
|
|
96
97
|
- `rowLimit`: Number - Maximum number of rows to fetch (default: 100)
|
|
97
|
-
- `waitSeconds`: Number -
|
|
98
|
+
- `waitSeconds`: Number - Base back-off delay in seconds for retrying rate-limited API calls (HTTP 429/503). Actual delay per retry is `waitSeconds × 2^attempt`, capped at 30 s. (default: 1)
|
|
98
99
|
- `dataJsonPath`: String - Path for languageData.json file (default: 'src/lib/languageData.json')
|
|
99
100
|
- `localesOutputPath`: String - Path for locales.ts file (default: 'src/i18n/locales.ts')
|
|
100
101
|
- `translationsOutputDir`: String - Directory for translations output (default: 'translations')
|
|
@@ -187,6 +188,37 @@ console.log(validLocales); // ['en', 'de']
|
|
|
187
188
|
const config = normalizeConfig({ waitSeconds: 2 });
|
|
188
189
|
```
|
|
189
190
|
|
|
191
|
+
## Auto-Creating a Spreadsheet
|
|
192
|
+
|
|
193
|
+
When no `GOOGLE_SPREADSHEET_ID` is set (and `autoCreate` is not `false`), the package automatically creates a new Google Spreadsheet on first run using your service-account credentials:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// No spreadsheetId needed — the package creates one for you
|
|
197
|
+
const translations = await getSpreadSheetData(['i18n'], {
|
|
198
|
+
spreadsheetTitle: 'MyProject Translations',
|
|
199
|
+
sourceLocale: 'en',
|
|
200
|
+
targetLocales: ['de', 'fr', 'es'],
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The created spreadsheet includes:
|
|
205
|
+
- A **`__welcome__`** sheet with setup instructions and your spreadsheet ID.
|
|
206
|
+
- An **`i18n`** starter sheet with common translation keys and `GOOGLETRANSLATE` formulas for each target locale.
|
|
207
|
+
|
|
208
|
+
The new spreadsheet ID is printed prominently to the console and, if a `.env` file exists in your working directory, is written to it automatically:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
✅ New spreadsheet created!
|
|
212
|
+
Title : MyProject Translations
|
|
213
|
+
URL : https://docs.google.com/spreadsheets/d/...
|
|
214
|
+
ID : 1abc...xyz
|
|
215
|
+
|
|
216
|
+
Add this to your .env file (or environment):
|
|
217
|
+
GOOGLE_SPREADSHEET_ID=1abc...xyz
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Set `autoCreate: false` to disable this behaviour and require an explicit ID.
|
|
221
|
+
|
|
190
222
|
## Bidirectional Sync Feature
|
|
191
223
|
|
|
192
224
|
This package supports bidirectional synchronization between local translation files and the Google Spreadsheet:
|
|
@@ -253,6 +285,102 @@ For more detailed examples, check out the [examples directory](examples) where y
|
|
|
253
285
|
- Auto-translation
|
|
254
286
|
- Next.js integration
|
|
255
287
|
|
|
288
|
+
## GitHub Action
|
|
289
|
+
|
|
290
|
+
This repository ships a composite GitHub Action that lets you fetch translations
|
|
291
|
+
in any workflow **without writing any Node.js scripts yourself**.
|
|
292
|
+
|
|
293
|
+
### Quick start
|
|
294
|
+
|
|
295
|
+
Add the following step to your workflow after checking out your repository:
|
|
296
|
+
|
|
297
|
+
```yaml
|
|
298
|
+
- name: Fetch translations
|
|
299
|
+
uses: el-j/google-sheet-translations@v1 # pin to a specific release tag for stability
|
|
300
|
+
with:
|
|
301
|
+
google-client-email: ${{ secrets.GOOGLE_CLIENT_EMAIL }}
|
|
302
|
+
google-private-key: ${{ secrets.GOOGLE_PRIVATE_KEY }}
|
|
303
|
+
google-spreadsheet-id: ${{ secrets.GOOGLE_SPREADSHEET_ID }}
|
|
304
|
+
sheet-titles: 'landingPage,about' # comma-separated sheet tab names
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Inputs
|
|
308
|
+
|
|
309
|
+
| Input | Required | Default | Description |
|
|
310
|
+
|-------|----------|---------|-------------|
|
|
311
|
+
| `google-client-email` | ✅ | — | Service-account e-mail (`GOOGLE_CLIENT_EMAIL`) |
|
|
312
|
+
| `google-private-key` | ✅ | — | Service-account private key (`GOOGLE_PRIVATE_KEY`) |
|
|
313
|
+
| `google-spreadsheet-id` | ✅ | — | Spreadsheet ID from the sheet URL (`GOOGLE_SPREADSHEET_ID`) |
|
|
314
|
+
| `sheet-titles` | ✅ | — | Comma-separated list of sheet tab names to process |
|
|
315
|
+
| `row-limit` | ❌ | `100` | Maximum rows to read per sheet |
|
|
316
|
+
| `wait-seconds` | ❌ | `1` | Base back-off delay in seconds for retrying rate-limited API calls (HTTP 429/503) |
|
|
317
|
+
| `translations-output-dir` | ❌ | `translations` | Directory for per-locale JSON files |
|
|
318
|
+
| `locales-output-path` | ❌ | `src/i18n/locales.ts` | Path for the generated `locales.ts` |
|
|
319
|
+
| `data-json-path` | ❌ | `src/lib/languageData.json` | Path for the `languageData.json` snapshot |
|
|
320
|
+
| `sync-local-changes` | ❌ | `true` | Push local changes back to the sheet before fetching |
|
|
321
|
+
| `node-version` | ❌ | `20` | Node.js version used to run the fetch script |
|
|
322
|
+
| `package-version` | ❌ | `latest` | Version of `@el-j/google-sheet-translations` to install |
|
|
323
|
+
|
|
324
|
+
### Outputs
|
|
325
|
+
|
|
326
|
+
| Output | Description |
|
|
327
|
+
|--------|-------------|
|
|
328
|
+
| `translations-dir` | Absolute path of the directory containing locale JSON files |
|
|
329
|
+
| `locales-file` | Absolute path of the generated `locales.ts` |
|
|
330
|
+
| `data-json-file` | Absolute path of the `languageData.json` snapshot |
|
|
331
|
+
|
|
332
|
+
### Full workflow example
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
name: Update Translations
|
|
336
|
+
|
|
337
|
+
on:
|
|
338
|
+
schedule:
|
|
339
|
+
- cron: '0 6 * * 1' # every Monday at 06:00 UTC
|
|
340
|
+
workflow_dispatch:
|
|
341
|
+
|
|
342
|
+
jobs:
|
|
343
|
+
update-translations:
|
|
344
|
+
runs-on: ubuntu-latest
|
|
345
|
+
permissions:
|
|
346
|
+
contents: write
|
|
347
|
+
|
|
348
|
+
steps:
|
|
349
|
+
- name: Checkout
|
|
350
|
+
uses: actions/checkout@v4
|
|
351
|
+
|
|
352
|
+
- name: Fetch translations
|
|
353
|
+
id: translations
|
|
354
|
+
uses: el-j/google-sheet-translations@v1
|
|
355
|
+
with:
|
|
356
|
+
google-client-email: ${{ secrets.GOOGLE_CLIENT_EMAIL }}
|
|
357
|
+
google-private-key: ${{ secrets.GOOGLE_PRIVATE_KEY }}
|
|
358
|
+
google-spreadsheet-id: ${{ secrets.GOOGLE_SPREADSHEET_ID }}
|
|
359
|
+
sheet-titles: 'landingPage,about'
|
|
360
|
+
translations-output-dir: 'src/translations'
|
|
361
|
+
locales-output-path: 'src/i18n/locales.ts'
|
|
362
|
+
data-json-path: 'src/lib/languageData.json'
|
|
363
|
+
|
|
364
|
+
- name: Commit updated translations
|
|
365
|
+
uses: stefanzweifel/git-auto-commit-action@v5
|
|
366
|
+
with:
|
|
367
|
+
commit_message: 'chore(i18n): update translations from Google Sheets'
|
|
368
|
+
file_pattern: |
|
|
369
|
+
${{ steps.translations.outputs.translations-dir }}/**
|
|
370
|
+
${{ steps.translations.outputs.locales-file }}
|
|
371
|
+
${{ steps.translations.outputs.data-json-file }}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Required secrets
|
|
375
|
+
|
|
376
|
+
Store these as [encrypted repository secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets):
|
|
377
|
+
|
|
378
|
+
| Secret | Description |
|
|
379
|
+
|--------|-------------|
|
|
380
|
+
| `GOOGLE_CLIENT_EMAIL` | Service-account e-mail from your Google Cloud credentials JSON |
|
|
381
|
+
| `GOOGLE_PRIVATE_KEY` | Private key from your Google Cloud credentials JSON (include the full PEM block) |
|
|
382
|
+
| `GOOGLE_SPREADSHEET_ID` | The long ID found in the spreadsheet URL: `…/spreadsheets/d/<ID>/edit` |
|
|
383
|
+
|
|
256
384
|
## License
|
|
257
385
|
|
|
258
386
|
MIT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSpreadSheetData.d.ts","sourceRoot":"","sources":["../src/getSpreadSheetData.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getSpreadSheetData.d.ts","sourceRoot":"","sources":["../src/getSpreadSheetData.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAOxF,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAsChC,wBAAsB,kBAAkB,CACvC,SAAS,CAAC,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE,kBAAuB,EAChC,aAAa,SAAI,GACf,OAAO,CAAC,eAAe,CAAC,CAyJ1B;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,118 +1,167 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.DEFAULT_WAIT_SECONDS = void 0;
|
|
4
7
|
exports.getSpreadSheetData = getSpreadSheetData;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
5
10
|
const google_spreadsheet_1 = require("google-spreadsheet");
|
|
6
|
-
const wait_1 = require("./utils/wait");
|
|
7
11
|
const auth_1 = require("./utils/auth");
|
|
8
|
-
const validateEnv_1 = require("./utils/validateEnv");
|
|
9
12
|
const configurationHandler_1 = require("./utils/configurationHandler");
|
|
10
13
|
const sheetProcessor_1 = require("./utils/sheetProcessor");
|
|
11
14
|
const fileWriter_1 = require("./utils/fileWriter");
|
|
12
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");
|
|
13
19
|
const constants_1 = require("./constants");
|
|
14
20
|
Object.defineProperty(exports, "DEFAULT_WAIT_SECONDS", { enumerable: true, get: function () { return constants_1.DEFAULT_WAIT_SECONDS; } });
|
|
15
21
|
/**
|
|
16
|
-
* Fetches and processes data from a Google Spreadsheet
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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.
|
|
20
32
|
*/
|
|
21
33
|
const MAX_SYNC_REFRESH_DEPTH = 1;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
// Get spreadsheet ID from environment variables
|
|
26
|
-
const { GOOGLE_SPREADSHEET_ID } = (0, validateEnv_1.validateEnv)();
|
|
27
|
-
// Initialize Google Spreadsheet connection
|
|
28
|
-
const serviceAuthClient = (0, auth_1.createAuthClient)();
|
|
29
|
-
const doc = new google_spreadsheet_1.GoogleSpreadsheet(GOOGLE_SPREADSHEET_ID, serviceAuthClient);
|
|
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');
|
|
30
37
|
try {
|
|
31
|
-
|
|
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}`);
|
|
32
53
|
}
|
|
33
54
|
catch (err) {
|
|
34
|
-
|
|
55
|
+
console.warn(` Could not write .env: ${err.message}`);
|
|
35
56
|
}
|
|
36
|
-
|
|
57
|
+
}
|
|
58
|
+
async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
|
|
59
|
+
const config = (0, configurationHandler_1.normalizeConfig)(options);
|
|
60
|
+
const baseDelayMs = config.waitSeconds * 1000;
|
|
37
61
|
const docTitle = _docTitle ?? [];
|
|
38
62
|
if (docTitle.length === 0) {
|
|
39
63
|
console.warn("No sheet titles provided, cannot process spreadsheet data");
|
|
40
64
|
return {};
|
|
41
65
|
}
|
|
42
|
-
// Always include i18n sheet if not already present
|
|
43
66
|
if (!docTitle.includes("i18n")) {
|
|
44
67
|
docTitle.push("i18n");
|
|
45
68
|
}
|
|
46
|
-
console.log(`Processing ${docTitle.length} sheets: ${docTitle.join(", ")}`);
|
|
47
|
-
// Initialize result containers
|
|
48
69
|
const finalTranslations = {};
|
|
49
70
|
const allLocales = new Set();
|
|
50
|
-
const localesWithContent = new Set();
|
|
51
|
-
const globalLocaleMapping = {};
|
|
52
|
-
const globalOriginalMapping = {};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
await (0, wait_1.wait)(config.waitSeconds, `before get cells for sheet: ${title}`);
|
|
56
|
-
const sheet = doc.sheetsByTitle[title];
|
|
57
|
-
if (!sheet) {
|
|
58
|
-
console.warn(`Sheet "${title}" not found in the document`);
|
|
71
|
+
const localesWithContent = new Set();
|
|
72
|
+
const globalLocaleMapping = {};
|
|
73
|
+
const globalOriginalMapping = {};
|
|
74
|
+
function mergeResult(result, title) {
|
|
75
|
+
if (!result.success)
|
|
59
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.");
|
|
60
105
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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);
|
|
68
133
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
globalOriginalMapping[original] = normalized;
|
|
72
|
-
}
|
|
134
|
+
else {
|
|
135
|
+
throw new Error("No spreadsheet ID provided. Set GOOGLE_SPREADSHEET_ID or pass spreadsheetId in options.");
|
|
73
136
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// Check if this locale actually has translation content (not just empty objects)
|
|
89
|
-
const hasActualTranslations = Object.values(result.translations[locale]).some(sheetTranslations => Object.keys(sheetTranslations).length > 0);
|
|
90
|
-
if (hasActualTranslations) {
|
|
91
|
-
localesWithContent.add(locale);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
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;
|
|
94
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);
|
|
95
157
|
}
|
|
96
|
-
}
|
|
97
|
-
// Use locales with actual content for the locales file, fall back to all locales if none found
|
|
158
|
+
}
|
|
98
159
|
const localesForOutput = localesWithContent.size > 0 ? Array.from(localesWithContent) : Array.from(allLocales);
|
|
99
160
|
const allLocalesArray = Array.from(allLocales);
|
|
100
|
-
// Handle bidirectional sync if needed
|
|
101
|
-
const syncResult = await (0, syncManager_1.handleBidirectionalSync)(doc, config.dataJsonPath, config.translationsOutputDir, config.syncLocalChanges, config.autoTranslate, finalTranslations, config.waitSeconds, globalLocaleMapping);
|
|
102
|
-
// If sync requested a refresh, recursively call with updated data (depth-limited)
|
|
103
|
-
if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
|
|
104
|
-
return getSpreadSheetData(_docTitle, {
|
|
105
|
-
...options,
|
|
106
|
-
syncLocalChanges: false,
|
|
107
|
-
}, _refreshDepth + 1);
|
|
108
|
-
}
|
|
109
|
-
// Write output files - use all locales for translation files but filtered locales for locales.ts
|
|
110
161
|
(0, fileWriter_1.writeTranslationFiles)(finalTranslations, allLocalesArray, config.translationsOutputDir);
|
|
111
162
|
(0, fileWriter_1.writeLocalesFile)(localesForOutput, globalLocaleMapping, config.localesOutputPath);
|
|
112
163
|
console.log(`Writing locales file with ${localesForOutput.length} locales that have actual translations:`, localesForOutput);
|
|
113
|
-
|
|
114
|
-
const hasData = Object.keys(finalTranslations).length > 0;
|
|
115
|
-
if (hasData) {
|
|
164
|
+
if (Object.keys(finalTranslations).length > 0) {
|
|
116
165
|
(0, fileWriter_1.writeLanguageDataFile)(finalTranslations, allLocalesArray, config.dataJsonPath);
|
|
117
166
|
}
|
|
118
167
|
return finalTranslations;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSpreadSheetData.js","sourceRoot":"","sources":["../src/getSpreadSheetData.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getSpreadSheetData.js","sourceRoot":"","sources":["../src/getSpreadSheetData.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
export { getSpreadSheetData, DEFAULT_WAIT_SECONDS } from './getSpreadSheetData';
|
|
6
6
|
export type { SpreadsheetOptions } from './utils/configurationHandler';
|
|
7
7
|
export { wait } from './utils/wait';
|
|
8
|
+
export { withRetry } from './utils/rateLimiter';
|
|
8
9
|
export { validateEnv } from './utils/validateEnv';
|
|
9
10
|
export { createAuthClient } from './utils/auth';
|
|
10
11
|
export { convertToDataJsonFormat } from './utils/dataConverter/convertToDataJsonFormat';
|
|
11
12
|
export { convertFromDataJsonFormat } from './utils/dataConverter/convertFromDataJsonFormat';
|
|
12
13
|
export { findLocalChanges } from './utils/dataConverter/findLocalChanges';
|
|
13
14
|
export { updateSpreadsheetWithLocalChanges } from './utils/spreadsheetUpdater';
|
|
15
|
+
export { readPublicSheet } from './utils/publicSheetReader';
|
|
16
|
+
export { createSpreadsheet } from './utils/spreadsheetCreator';
|
|
17
|
+
export { validateCredentials } from './utils/validateEnv';
|
|
14
18
|
export { isValidLocale, filterValidLocales } from './utils/localeFilter';
|
|
15
19
|
export type { TranslationData, TranslationValue, SheetRow, GoogleEnvVars, } from './types';
|
|
16
20
|
import { getSpreadSheetData } from './getSpreadSheetData';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,eAAe,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,eAAe,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* v2.0.0 – public API surface
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.filterValidLocales = exports.isValidLocale = exports.updateSpreadsheetWithLocalChanges = exports.findLocalChanges = exports.convertFromDataJsonFormat = exports.convertToDataJsonFormat = exports.createAuthClient = exports.validateEnv = exports.wait = exports.DEFAULT_WAIT_SECONDS = exports.getSpreadSheetData = void 0;
|
|
7
|
+
exports.filterValidLocales = exports.isValidLocale = exports.validateCredentials = exports.createSpreadsheet = exports.readPublicSheet = exports.updateSpreadsheetWithLocalChanges = exports.findLocalChanges = exports.convertFromDataJsonFormat = exports.convertToDataJsonFormat = exports.createAuthClient = exports.validateEnv = exports.withRetry = exports.wait = exports.DEFAULT_WAIT_SECONDS = exports.getSpreadSheetData = void 0;
|
|
8
8
|
// Main entry point
|
|
9
9
|
var getSpreadSheetData_1 = require("./getSpreadSheetData");
|
|
10
10
|
Object.defineProperty(exports, "getSpreadSheetData", { enumerable: true, get: function () { return getSpreadSheetData_1.getSpreadSheetData; } });
|
|
@@ -12,6 +12,8 @@ Object.defineProperty(exports, "DEFAULT_WAIT_SECONDS", { enumerable: true, get:
|
|
|
12
12
|
// Utility functions required by dependents
|
|
13
13
|
var wait_1 = require("./utils/wait");
|
|
14
14
|
Object.defineProperty(exports, "wait", { enumerable: true, get: function () { return wait_1.wait; } });
|
|
15
|
+
var rateLimiter_1 = require("./utils/rateLimiter");
|
|
16
|
+
Object.defineProperty(exports, "withRetry", { enumerable: true, get: function () { return rateLimiter_1.withRetry; } });
|
|
15
17
|
var validateEnv_1 = require("./utils/validateEnv");
|
|
16
18
|
Object.defineProperty(exports, "validateEnv", { enumerable: true, get: function () { return validateEnv_1.validateEnv; } });
|
|
17
19
|
var auth_1 = require("./utils/auth");
|
|
@@ -24,6 +26,14 @@ var findLocalChanges_1 = require("./utils/dataConverter/findLocalChanges");
|
|
|
24
26
|
Object.defineProperty(exports, "findLocalChanges", { enumerable: true, get: function () { return findLocalChanges_1.findLocalChanges; } });
|
|
25
27
|
var spreadsheetUpdater_1 = require("./utils/spreadsheetUpdater");
|
|
26
28
|
Object.defineProperty(exports, "updateSpreadsheetWithLocalChanges", { enumerable: true, get: function () { return spreadsheetUpdater_1.updateSpreadsheetWithLocalChanges; } });
|
|
29
|
+
// Public (unauthenticated) sheet reader
|
|
30
|
+
var publicSheetReader_1 = require("./utils/publicSheetReader");
|
|
31
|
+
Object.defineProperty(exports, "readPublicSheet", { enumerable: true, get: function () { return publicSheetReader_1.readPublicSheet; } });
|
|
32
|
+
// Auto-create spreadsheet utility
|
|
33
|
+
var spreadsheetCreator_1 = require("./utils/spreadsheetCreator");
|
|
34
|
+
Object.defineProperty(exports, "createSpreadsheet", { enumerable: true, get: function () { return spreadsheetCreator_1.createSpreadsheet; } });
|
|
35
|
+
var validateEnv_2 = require("./utils/validateEnv");
|
|
36
|
+
Object.defineProperty(exports, "validateCredentials", { enumerable: true, get: function () { return validateEnv_2.validateCredentials; } });
|
|
27
37
|
// Locale validation utilities (useful standalone)
|
|
28
38
|
var localeFilter_1 = require("./utils/localeFilter");
|
|
29
39
|
Object.defineProperty(exports, "isValidLocale", { enumerable: true, get: function () { return localeFilter_1.isValidLocale; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,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,kDAAkD;AAClD,qDAAyE;AAAhE,6GAAA,aAAa,OAAA;AAAE,kHAAA,kBAAkB,OAAA;AAU1C,iBAAiB;AACjB,6DAA0D;AAC1D,kBAAe,uCAAkB,CAAC"}
|
|
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/utils/auth.js
CHANGED
|
@@ -8,7 +8,7 @@ const validateEnv_1 = require("./validateEnv");
|
|
|
8
8
|
* @returns JWT authentication client
|
|
9
9
|
*/
|
|
10
10
|
function createAuthClient() {
|
|
11
|
-
const { GOOGLE_CLIENT_EMAIL, GOOGLE_PRIVATE_KEY } = (0, validateEnv_1.
|
|
11
|
+
const { GOOGLE_CLIENT_EMAIL, GOOGLE_PRIVATE_KEY } = (0, validateEnv_1.validateCredentials)();
|
|
12
12
|
// GitHub Actions (and many CI systems) store secrets with literal `\n`
|
|
13
13
|
// instead of real newlines. The PEM key must have actual newlines for
|
|
14
14
|
// OpenSSL to parse it; replace any escaped sequences before use.
|
package/dist/utils/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":";;AAOA,4CAaC;AApBD,6DAA0C;AAC1C,+
|
|
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"}
|
|
@@ -3,12 +3,50 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface SpreadsheetOptions {
|
|
5
5
|
rowLimit?: number;
|
|
6
|
+
/**
|
|
7
|
+
* Base back-off delay in seconds used when retrying Google Sheets API
|
|
8
|
+
* calls that fail with a rate-limit response (HTTP 429 / 503).
|
|
9
|
+
* The actual delay for each retry attempt is `waitSeconds * 2^attempt`,
|
|
10
|
+
* capped at 30 seconds. Defaults to 1.
|
|
11
|
+
*/
|
|
6
12
|
waitSeconds?: number;
|
|
7
13
|
dataJsonPath?: string;
|
|
8
14
|
localesOutputPath?: string;
|
|
9
15
|
translationsOutputDir?: string;
|
|
10
16
|
syncLocalChanges?: boolean;
|
|
11
17
|
autoTranslate?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Google Spreadsheet ID.
|
|
20
|
+
* Overrides the `GOOGLE_SPREADSHEET_ID` environment variable when provided.
|
|
21
|
+
*/
|
|
22
|
+
spreadsheetId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* When `true`, the spreadsheet is read through the Google Visualization
|
|
25
|
+
* API without any service-account credentials.
|
|
26
|
+
*
|
|
27
|
+
* The spreadsheet must be shared as **"Anyone with link can view"** (or
|
|
28
|
+
* broader). Bidirectional sync and auto-translate are unavailable in
|
|
29
|
+
* this mode because they require write access.
|
|
30
|
+
*/
|
|
31
|
+
publicSheet?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Automatically create a new Google Spreadsheet when no spreadsheetId is
|
|
34
|
+
* available and the caller is in authenticated mode.
|
|
35
|
+
* Default: `true` (creation happens on the first run when no ID is set).
|
|
36
|
+
*/
|
|
37
|
+
autoCreate?: boolean;
|
|
38
|
+
/** Title for the auto-created spreadsheet (default: "google-sheet-translations"). */
|
|
39
|
+
spreadsheetTitle?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Source locale used when seeding the auto-created spreadsheet with
|
|
42
|
+
* GOOGLETRANSLATE formulas (default: "en").
|
|
43
|
+
*/
|
|
44
|
+
sourceLocale?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Target locales for GOOGLETRANSLATE formulas in the auto-created spreadsheet.
|
|
47
|
+
* Default: ['de', 'fr', 'es', 'it', 'pt', 'ja', 'zh'].
|
|
48
|
+
*/
|
|
49
|
+
targetLocales?: string[];
|
|
12
50
|
}
|
|
13
51
|
/**
|
|
14
52
|
* Normalized configuration with all defaults applied
|
|
@@ -21,6 +59,12 @@ export interface NormalizedConfig {
|
|
|
21
59
|
translationsOutputDir: string;
|
|
22
60
|
syncLocalChanges: boolean;
|
|
23
61
|
autoTranslate: boolean;
|
|
62
|
+
spreadsheetId: string | undefined;
|
|
63
|
+
publicSheet: boolean;
|
|
64
|
+
autoCreate: boolean;
|
|
65
|
+
spreadsheetTitle: string;
|
|
66
|
+
sourceLocale: string;
|
|
67
|
+
targetLocales: string[];
|
|
24
68
|
}
|
|
25
69
|
/**
|
|
26
70
|
* Normalizes configuration options by applying defaults
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurationHandler.d.ts","sourceRoot":"","sources":["../../src/utils/configurationHandler.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"configurationHandler.d.ts","sourceRoot":"","sources":["../../src/utils/configurationHandler.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,kBAAuB,GAAG,gBAAgB,CAgBlF"}
|
|
@@ -14,10 +14,16 @@ function normalizeConfig(options = {}) {
|
|
|
14
14
|
rowLimit: options.rowLimit ?? 100,
|
|
15
15
|
waitSeconds: options.waitSeconds ?? constants_1.DEFAULT_WAIT_SECONDS,
|
|
16
16
|
dataJsonPath: options.dataJsonPath ?? node_path_1.default.join(process.cwd(), "src/lib/languageData.json"),
|
|
17
|
-
localesOutputPath: options.localesOutputPath ?? "src/i18n/locales.ts",
|
|
18
|
-
translationsOutputDir: options.translationsOutputDir ?? "translations",
|
|
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
19
|
syncLocalChanges: options.syncLocalChanges !== false, // Default to true
|
|
20
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'],
|
|
21
27
|
};
|
|
22
28
|
}
|
|
23
29
|
//# sourceMappingURL=configurationHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurationHandler.js","sourceRoot":"","sources":["../../src/utils/configurationHandler.ts"],"names":[],"mappings":";;;;;
|
|
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"}
|