@el-j/google-sheet-translations 2.0.1 → 2.1.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"action-entrypoint.d.ts","sourceRoot":"","sources":["../src/action-entrypoint.ts"],"names":[],"mappings":"AAKA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA6DzC"}
1
+ {"version":3,"file":"action-entrypoint.d.ts","sourceRoot":"","sources":["../src/action-entrypoint.ts"],"names":[],"mappings":"AAKA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA+DzC"}
package/dist/esm/index.js CHANGED
@@ -80,7 +80,11 @@ function normalizeConfig(options = {}) {
80
80
  // Default to true
81
81
  spreadsheetTitle: options.spreadsheetTitle ?? "google-sheet-translations",
82
82
  sourceLocale: options.sourceLocale ?? "en",
83
- targetLocales: options.targetLocales ?? ["de", "fr", "es", "it", "pt", "ja", "zh"]
83
+ targetLocales: options.targetLocales ?? ["de", "fr", "es", "it", "pt", "ja", "zh"],
84
+ override: options.override === true,
85
+ // Default to false
86
+ cleanPush: options.cleanPush === true
87
+ // Default to false
84
88
  };
85
89
  }
86
90
 
@@ -390,11 +394,8 @@ function convertToDataJsonFormat(translationObj, locales) {
390
394
  projectData[sheetTitle] = {};
391
395
  for (const locale of locales) {
392
396
  if (translationObj?.[locale]?.[sheetTitle]) {
393
- projectData[sheetTitle][locale] = {};
394
397
  const translations = translationObj[locale][sheetTitle];
395
- for (const key of Object.keys(translations)) {
396
- projectData[sheetTitle][locale][key] = translations[key];
397
- }
398
+ projectData[sheetTitle][locale] = { ...translations };
398
399
  console.log(
399
400
  `Found ${Object.keys(translations).length} keys for locale ${locale} in sheet ${sheetTitle}`
400
401
  );
@@ -529,7 +530,7 @@ function columnIndexToLetter(index) {
529
530
  } while (i >= 0);
530
531
  return result;
531
532
  }
532
- async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}) {
533
+ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
533
534
  console.log("Updating spreadsheet with local changes...");
534
535
  const baseDelayMs = waitSeconds * 1e3;
535
536
  for (const sheetTitle of new Set(
@@ -589,6 +590,27 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
589
590
  });
590
591
  const newKeys = /* @__PURE__ */ new Map();
591
592
  const keyLocalesMap = /* @__PURE__ */ new Map();
593
+ const pushedLocaleHeadersPerKey = /* @__PURE__ */ new Map();
594
+ if (autoTranslate) {
595
+ for (const pushedLocale of Object.keys(changes)) {
596
+ if (!changes[pushedLocale]?.[sheetTitle]) continue;
597
+ for (const pushedKey of Object.keys(changes[pushedLocale][sheetTitle])) {
598
+ const pushedKeyLower = pushedKey.toLowerCase();
599
+ if (!existingKeys.has(pushedKeyLower)) continue;
600
+ let pushedHeader = getOriginalHeaderForLocale(pushedLocale, localeMapping);
601
+ if (!pushedHeader) {
602
+ const prefix = getLanguagePrefix(pushedLocale);
603
+ pushedHeader = originalHeaders.find((h) => getLanguagePrefix(h) === prefix);
604
+ }
605
+ if (pushedHeader) {
606
+ if (!pushedLocaleHeadersPerKey.has(pushedKeyLower)) {
607
+ pushedLocaleHeadersPerKey.set(pushedKeyLower, /* @__PURE__ */ new Set());
608
+ }
609
+ pushedLocaleHeadersPerKey.get(pushedKeyLower).add(pushedHeader.toLowerCase());
610
+ }
611
+ }
612
+ }
613
+ }
592
614
  for (const locale of Object.keys(changes)) {
593
615
  if (!changes[locale]?.[sheetTitle]) continue;
594
616
  const localeData = changes[locale][sheetTitle];
@@ -631,6 +653,35 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
631
653
  }
632
654
  if (localeHeader) {
633
655
  row.set(localeHeader, String(localeData[key]));
656
+ if (autoTranslate) {
657
+ const sourceHeaderLower = localeHeader.toLowerCase();
658
+ const sourceHeaderIndex = headerRow.indexOf(sourceHeaderLower);
659
+ if (sourceHeaderIndex >= 0) {
660
+ const sourceColumnLetter = columnIndexToLetter(sourceHeaderIndex);
661
+ const rowObj = row.toObject();
662
+ const pushedHeaders = pushedLocaleHeadersPerKey.get(keyLower) ?? /* @__PURE__ */ new Set();
663
+ for (const targetLocaleHeader of locales) {
664
+ const targetLower = targetLocaleHeader.toLowerCase();
665
+ if (targetLower === sourceHeaderLower) continue;
666
+ if (pushedHeaders.has(targetLower)) continue;
667
+ const targetHeaderIndex = headerRow.indexOf(targetLower);
668
+ if (targetHeaderIndex < 0) continue;
669
+ const exactTargetHeader = originalHeaders.find(
670
+ (h) => h.toLowerCase() === targetLower
671
+ );
672
+ if (!exactTargetHeader) continue;
673
+ const existingValue = rowObj[exactTargetHeader];
674
+ const isEmpty = !existingValue || existingValue.toString().trim() === "";
675
+ if (isEmpty || override) {
676
+ const targetColumnLetter = columnIndexToLetter(targetHeaderIndex);
677
+ row.set(
678
+ exactTargetHeader,
679
+ `=GOOGLETRANSLATE(INDIRECT("${sourceColumnLetter}"&ROW());$${sourceColumnLetter}$1;${targetColumnLetter}$1)`
680
+ );
681
+ }
682
+ }
683
+ }
684
+ }
634
685
  try {
635
686
  await withRetry(
636
687
  () => row.save(),
@@ -779,19 +830,23 @@ function readDataJson(dataJsonPath) {
779
830
  }
780
831
 
781
832
  // src/utils/syncManager.ts
782
- async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}) {
833
+ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}, override = false, cleanPush = false) {
783
834
  const result = {
784
835
  shouldRefresh: false,
785
836
  hasChanges: false
786
837
  };
787
838
  const localData = readDataJson(dataJsonPath);
788
839
  const dataJsonExists = localData !== null;
789
- const shouldSyncToSheet = syncLocalChanges && dataJsonExists && isDataJsonNewer(dataJsonPath, translationsOutputDir);
840
+ const shouldSyncToSheet = dataJsonExists && (cleanPush || syncLocalChanges && isDataJsonNewer(dataJsonPath, translationsOutputDir));
790
841
  if (!shouldSyncToSheet || !localData) {
791
842
  return result;
792
843
  }
793
- console.log("Local languageData.json is newer than translation files. Checking for changes...");
794
- const changes = findLocalChanges(localData, spreadsheetData);
844
+ if (cleanPush) {
845
+ console.log("Clean push enabled \u2013 pushing ALL keys from languageData.json to the spreadsheet...");
846
+ } else {
847
+ console.log("Local languageData.json is newer than translation files. Checking for changes...");
848
+ }
849
+ const changes = cleanPush ? localData : findLocalChanges(localData, spreadsheetData);
795
850
  const hasChanges = Object.keys(changes).length > 0 && Object.keys(changes).some(
796
851
  (locale) => Object.keys(changes[locale]).length > 0
797
852
  );
@@ -801,9 +856,10 @@ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir,
801
856
  }
802
857
  const localesCount = Object.keys(changes).length;
803
858
  const keysCount = Object.values(changes).flatMap((l) => Object.values(l)).flatMap((s) => Object.keys(s)).length;
804
- console.log(`Found local changes: ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
859
+ const pushMode = cleanPush ? "clean push" : "incremental sync";
860
+ console.log(`Found local changes (${pushMode}): ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
805
861
  try {
806
- await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping);
862
+ await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping, override);
807
863
  result.shouldRefresh = true;
808
864
  result.hasChanges = true;
809
865
  } catch (err) {
@@ -1132,7 +1188,9 @@ async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
1132
1188
  config.autoTranslate,
1133
1189
  finalTranslations,
1134
1190
  config.waitSeconds,
1135
- globalLocaleMapping
1191
+ globalLocaleMapping,
1192
+ config.override,
1193
+ config.cleanPush
1136
1194
  );
1137
1195
  if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
1138
1196
  return getSpreadSheetData(
@@ -1 +1 @@
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
+ {"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,CA2J1B;AAED,eAAe,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -145,7 +145,11 @@ function normalizeConfig(options = {}) {
145
145
  // Default to true
146
146
  spreadsheetTitle: options.spreadsheetTitle ?? "google-sheet-translations",
147
147
  sourceLocale: options.sourceLocale ?? "en",
148
- targetLocales: options.targetLocales ?? ["de", "fr", "es", "it", "pt", "ja", "zh"]
148
+ targetLocales: options.targetLocales ?? ["de", "fr", "es", "it", "pt", "ja", "zh"],
149
+ override: options.override === true,
150
+ // Default to false
151
+ cleanPush: options.cleanPush === true
152
+ // Default to false
149
153
  };
150
154
  }
151
155
 
@@ -455,11 +459,8 @@ function convertToDataJsonFormat(translationObj, locales) {
455
459
  projectData[sheetTitle] = {};
456
460
  for (const locale of locales) {
457
461
  if (translationObj?.[locale]?.[sheetTitle]) {
458
- projectData[sheetTitle][locale] = {};
459
462
  const translations = translationObj[locale][sheetTitle];
460
- for (const key of Object.keys(translations)) {
461
- projectData[sheetTitle][locale][key] = translations[key];
462
- }
463
+ projectData[sheetTitle][locale] = { ...translations };
463
464
  console.log(
464
465
  `Found ${Object.keys(translations).length} keys for locale ${locale} in sheet ${sheetTitle}`
465
466
  );
@@ -594,7 +595,7 @@ function columnIndexToLetter(index) {
594
595
  } while (i >= 0);
595
596
  return result;
596
597
  }
597
- async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}) {
598
+ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
598
599
  console.log("Updating spreadsheet with local changes...");
599
600
  const baseDelayMs = waitSeconds * 1e3;
600
601
  for (const sheetTitle of new Set(
@@ -654,6 +655,27 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
654
655
  });
655
656
  const newKeys = /* @__PURE__ */ new Map();
656
657
  const keyLocalesMap = /* @__PURE__ */ new Map();
658
+ const pushedLocaleHeadersPerKey = /* @__PURE__ */ new Map();
659
+ if (autoTranslate) {
660
+ for (const pushedLocale of Object.keys(changes)) {
661
+ if (!changes[pushedLocale]?.[sheetTitle]) continue;
662
+ for (const pushedKey of Object.keys(changes[pushedLocale][sheetTitle])) {
663
+ const pushedKeyLower = pushedKey.toLowerCase();
664
+ if (!existingKeys.has(pushedKeyLower)) continue;
665
+ let pushedHeader = getOriginalHeaderForLocale(pushedLocale, localeMapping);
666
+ if (!pushedHeader) {
667
+ const prefix = getLanguagePrefix(pushedLocale);
668
+ pushedHeader = originalHeaders.find((h) => getLanguagePrefix(h) === prefix);
669
+ }
670
+ if (pushedHeader) {
671
+ if (!pushedLocaleHeadersPerKey.has(pushedKeyLower)) {
672
+ pushedLocaleHeadersPerKey.set(pushedKeyLower, /* @__PURE__ */ new Set());
673
+ }
674
+ pushedLocaleHeadersPerKey.get(pushedKeyLower).add(pushedHeader.toLowerCase());
675
+ }
676
+ }
677
+ }
678
+ }
657
679
  for (const locale of Object.keys(changes)) {
658
680
  if (!changes[locale]?.[sheetTitle]) continue;
659
681
  const localeData = changes[locale][sheetTitle];
@@ -696,6 +718,35 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
696
718
  }
697
719
  if (localeHeader) {
698
720
  row.set(localeHeader, String(localeData[key]));
721
+ if (autoTranslate) {
722
+ const sourceHeaderLower = localeHeader.toLowerCase();
723
+ const sourceHeaderIndex = headerRow.indexOf(sourceHeaderLower);
724
+ if (sourceHeaderIndex >= 0) {
725
+ const sourceColumnLetter = columnIndexToLetter(sourceHeaderIndex);
726
+ const rowObj = row.toObject();
727
+ const pushedHeaders = pushedLocaleHeadersPerKey.get(keyLower) ?? /* @__PURE__ */ new Set();
728
+ for (const targetLocaleHeader of locales) {
729
+ const targetLower = targetLocaleHeader.toLowerCase();
730
+ if (targetLower === sourceHeaderLower) continue;
731
+ if (pushedHeaders.has(targetLower)) continue;
732
+ const targetHeaderIndex = headerRow.indexOf(targetLower);
733
+ if (targetHeaderIndex < 0) continue;
734
+ const exactTargetHeader = originalHeaders.find(
735
+ (h) => h.toLowerCase() === targetLower
736
+ );
737
+ if (!exactTargetHeader) continue;
738
+ const existingValue = rowObj[exactTargetHeader];
739
+ const isEmpty = !existingValue || existingValue.toString().trim() === "";
740
+ if (isEmpty || override) {
741
+ const targetColumnLetter = columnIndexToLetter(targetHeaderIndex);
742
+ row.set(
743
+ exactTargetHeader,
744
+ `=GOOGLETRANSLATE(INDIRECT("${sourceColumnLetter}"&ROW());$${sourceColumnLetter}$1;${targetColumnLetter}$1)`
745
+ );
746
+ }
747
+ }
748
+ }
749
+ }
699
750
  try {
700
751
  await withRetry(
701
752
  () => row.save(),
@@ -844,19 +895,23 @@ function readDataJson(dataJsonPath) {
844
895
  }
845
896
 
846
897
  // src/utils/syncManager.ts
847
- async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}) {
898
+ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}, override = false, cleanPush = false) {
848
899
  const result = {
849
900
  shouldRefresh: false,
850
901
  hasChanges: false
851
902
  };
852
903
  const localData = readDataJson(dataJsonPath);
853
904
  const dataJsonExists = localData !== null;
854
- const shouldSyncToSheet = syncLocalChanges && dataJsonExists && isDataJsonNewer(dataJsonPath, translationsOutputDir);
905
+ const shouldSyncToSheet = dataJsonExists && (cleanPush || syncLocalChanges && isDataJsonNewer(dataJsonPath, translationsOutputDir));
855
906
  if (!shouldSyncToSheet || !localData) {
856
907
  return result;
857
908
  }
858
- console.log("Local languageData.json is newer than translation files. Checking for changes...");
859
- const changes = findLocalChanges(localData, spreadsheetData);
909
+ if (cleanPush) {
910
+ console.log("Clean push enabled \u2013 pushing ALL keys from languageData.json to the spreadsheet...");
911
+ } else {
912
+ console.log("Local languageData.json is newer than translation files. Checking for changes...");
913
+ }
914
+ const changes = cleanPush ? localData : findLocalChanges(localData, spreadsheetData);
860
915
  const hasChanges = Object.keys(changes).length > 0 && Object.keys(changes).some(
861
916
  (locale) => Object.keys(changes[locale]).length > 0
862
917
  );
@@ -866,9 +921,10 @@ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir,
866
921
  }
867
922
  const localesCount = Object.keys(changes).length;
868
923
  const keysCount = Object.values(changes).flatMap((l) => Object.values(l)).flatMap((s) => Object.keys(s)).length;
869
- console.log(`Found local changes: ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
924
+ const pushMode = cleanPush ? "clean push" : "incremental sync";
925
+ console.log(`Found local changes (${pushMode}): ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
870
926
  try {
871
- await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping);
927
+ await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping, override);
872
928
  result.shouldRefresh = true;
873
929
  result.hasChanges = true;
874
930
  } catch (err) {
@@ -1197,7 +1253,9 @@ async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
1197
1253
  config.autoTranslate,
1198
1254
  finalTranslations,
1199
1255
  config.waitSeconds,
1200
- globalLocaleMapping
1256
+ globalLocaleMapping,
1257
+ config.override,
1258
+ config.cleanPush
1201
1259
  );
1202
1260
  if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
1203
1261
  return getSpreadSheetData(
@@ -47,6 +47,23 @@ export interface SpreadsheetOptions {
47
47
  * Default: ['de', 'fr', 'es', 'it', 'pt', 'ja', 'zh'].
48
48
  */
49
49
  targetLocales?: string[];
50
+ /**
51
+ * When `true`, existing translations in other language columns are overwritten
52
+ * with GOOGLETRANSLATE formulas when `autoTranslate` is also enabled and keys
53
+ * are pushed. When `false` (the default), only **empty** cells receive a
54
+ * formula – cells that already contain a translation are left untouched.
55
+ */
56
+ override?: boolean;
57
+ /**
58
+ * When `true`, **all** keys from the local `languageData.json` are pushed to
59
+ * the spreadsheet – including keys that already exist there. This is useful
60
+ * when the file has been copied from another project and the spreadsheet needs
61
+ * a complete refresh. The file-timestamp guard (`isDataJsonNewer`) is
62
+ * bypassed. Whether existing cell values are overwritten depends on the usual
63
+ * `override` + `autoTranslate` flags. Implies `syncLocalChanges`.
64
+ * Default: `false`.
65
+ */
66
+ cleanPush?: boolean;
50
67
  }
51
68
  /**
52
69
  * Normalized configuration with all defaults applied
@@ -65,6 +82,8 @@ export interface NormalizedConfig {
65
82
  spreadsheetTitle: string;
66
83
  sourceLocale: string;
67
84
  targetLocales: string[];
85
+ override: boolean;
86
+ cleanPush: boolean;
68
87
  }
69
88
  /**
70
89
  * 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;;;;;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"}
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;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;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;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,kBAAuB,GAAG,gBAAgB,CAkBlF"}
@@ -1 +1 @@
1
- {"version":3,"file":"convertToDataJsonFormat.d.ts","sourceRoot":"","sources":["../../../src/utils/dataConverter/convertToDataJsonFormat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACtC,cAAc,EAAE,eAAe,EAC/B,OAAO,EAAE,MAAM,EAAE,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAuD3B;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"convertToDataJsonFormat.d.ts","sourceRoot":"","sources":["../../../src/utils/dataConverter/convertToDataJsonFormat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACtC,cAAc,EAAE,eAAe,EAC/B,OAAO,EAAE,MAAM,EAAE,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAmD3B;AAED,eAAe,uBAAuB,CAAC"}
@@ -8,6 +8,8 @@ import type { TranslationData } from "../types";
8
8
  * - For languages missing translations, it automatically adds Google Translate formulas
9
9
  * - The formula format is: =GOOGLETRANSLATE(INDIRECT(sourceColumn&ROW());$sourceColumn$1;targetColumn$1)
10
10
  * - This dynamic formula uses cell references for language codes and automatically adapts to the correct row
11
+ * - For **existing** keys the same logic applies: empty cells in other language columns receive a
12
+ * formula; cells that already contain a translation are only overwritten when `override` is true.
11
13
  *
12
14
  * If a sheet named `sheetTitle` does not yet exist in the document and `localeMapping` is
13
15
  * non-empty, the sheet is **created automatically** with "key" as the first column followed by
@@ -24,7 +26,10 @@ import type { TranslationData } from "../types";
24
26
  * @param waitSeconds - Base back-off delay in seconds for retrying rate-limited API calls
25
27
  * @param autoTranslate - Whether to add Google Translate formulas for missing translations (default: false)
26
28
  * @param localeMapping - Mapping from normalized locale codes to original spreadsheet headers
29
+ * @param override - When true AND autoTranslate is true, existing translations in other language
30
+ * columns are overwritten with GOOGLETRANSLATE formulas. When false (default) only empty cells
31
+ * receive a formula.
27
32
  * @returns Promise that resolves when the update is complete
28
33
  */
29
- export declare function updateSpreadsheetWithLocalChanges(doc: GoogleSpreadsheet, changes: TranslationData, waitSeconds: number, autoTranslate?: boolean, localeMapping?: Record<string, string>): Promise<void>;
34
+ export declare function updateSpreadsheetWithLocalChanges(doc: GoogleSpreadsheet, changes: TranslationData, waitSeconds: number, autoTranslate?: boolean, localeMapping?: Record<string, string>, override?: boolean): Promise<void>;
30
35
  //# sourceMappingURL=spreadsheetUpdater.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spreadsheetUpdater.d.ts","sourceRoot":"","sources":["../../src/utils/spreadsheetUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAA8B,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAgBhD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,iCAAiC,CACnD,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,EACnB,aAAa,UAAQ,EACrB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC3C,OAAO,CAAC,IAAI,CAAC,CA4Pf"}
1
+ {"version":3,"file":"spreadsheetUpdater.d.ts","sourceRoot":"","sources":["../../src/utils/spreadsheetUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAA8B,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAgBhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,iCAAiC,CACnD,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,EACnB,aAAa,UAAQ,EACrB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC1C,QAAQ,UAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAsUf"}
@@ -17,7 +17,9 @@ export interface SyncResult {
17
17
  * @param spreadsheetData Current data from the spreadsheet
18
18
  * @param waitSeconds Time to wait between API calls
19
19
  * @param localeMapping Mapping from normalized locale codes to original spreadsheet headers
20
+ * @param override When true AND autoTranslate is true, overwrite existing translations with formulas
21
+ * @param cleanPush When true, push ALL keys from localData (bypasses timestamp guard and diff)
20
22
  * @returns Sync operation result
21
23
  */
22
- export declare function handleBidirectionalSync(doc: GoogleSpreadsheet, dataJsonPath: string, translationsOutputDir: string, syncLocalChanges: boolean, autoTranslate: boolean, spreadsheetData: TranslationData, waitSeconds: number, localeMapping?: Record<string, string>): Promise<SyncResult>;
24
+ export declare function handleBidirectionalSync(doc: GoogleSpreadsheet, dataJsonPath: string, translationsOutputDir: string, syncLocalChanges: boolean, autoTranslate: boolean, spreadsheetData: TranslationData, waitSeconds: number, localeMapping?: Record<string, string>, override?: boolean, cleanPush?: boolean): Promise<SyncResult>;
23
25
  //# sourceMappingURL=syncManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncManager.d.ts","sourceRoot":"","sources":["../../src/utils/syncManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhD;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,qBAAqB,EAAE,MAAM,EAC7B,gBAAgB,EAAE,OAAO,EACzB,aAAa,EAAE,OAAO,EACtB,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,OAAO,CAAC,UAAU,CAAC,CAoDrB"}
1
+ {"version":3,"file":"syncManager.d.ts","sourceRoot":"","sources":["../../src/utils/syncManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhD;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,qBAAqB,EAAE,MAAM,EAC7B,gBAAgB,EAAE,OAAO,EACzB,aAAa,EAAE,OAAO,EACtB,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC1C,QAAQ,UAAQ,EAChB,SAAS,UAAQ,GACf,OAAO,CAAC,UAAU,CAAC,CA4DrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@el-j/google-sheet-translations",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "A package to manage translations stored in Google Spreadsheets",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -75,10 +75,10 @@
75
75
  "@semantic-release/npm": "^13.1.5",
76
76
  "@semantic-release/release-notes-generator": "^14.1.0",
77
77
  "@types/jest": "^30.0.0",
78
- "@types/node": "^25.4.0",
78
+ "@types/node": "^25.5.0",
79
79
  "@typescript-eslint/eslint-plugin": "^8.57.0",
80
80
  "@typescript-eslint/parser": "^8.57.0",
81
- "esbuild": "^0.26.0",
81
+ "esbuild": "^0.27.4",
82
82
  "conventional-changelog-conventionalcommits": "^9.3.0",
83
83
  "dotenv": "17.3.1",
84
84
  "eslint": "^10.0.3",