@el-j/google-sheet-translations 2.0.1 → 2.1.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.
@@ -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
 
@@ -529,7 +533,7 @@ function columnIndexToLetter(index) {
529
533
  } while (i >= 0);
530
534
  return result;
531
535
  }
532
- async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}) {
536
+ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
533
537
  console.log("Updating spreadsheet with local changes...");
534
538
  const baseDelayMs = waitSeconds * 1e3;
535
539
  for (const sheetTitle of new Set(
@@ -589,6 +593,27 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
589
593
  });
590
594
  const newKeys = /* @__PURE__ */ new Map();
591
595
  const keyLocalesMap = /* @__PURE__ */ new Map();
596
+ const pushedLocaleHeadersPerKey = /* @__PURE__ */ new Map();
597
+ if (autoTranslate) {
598
+ for (const pushedLocale of Object.keys(changes)) {
599
+ if (!changes[pushedLocale]?.[sheetTitle]) continue;
600
+ for (const pushedKey of Object.keys(changes[pushedLocale][sheetTitle])) {
601
+ const pushedKeyLower = pushedKey.toLowerCase();
602
+ if (!existingKeys.has(pushedKeyLower)) continue;
603
+ let pushedHeader = getOriginalHeaderForLocale(pushedLocale, localeMapping);
604
+ if (!pushedHeader) {
605
+ const prefix = getLanguagePrefix(pushedLocale);
606
+ pushedHeader = originalHeaders.find((h) => getLanguagePrefix(h) === prefix);
607
+ }
608
+ if (pushedHeader) {
609
+ if (!pushedLocaleHeadersPerKey.has(pushedKeyLower)) {
610
+ pushedLocaleHeadersPerKey.set(pushedKeyLower, /* @__PURE__ */ new Set());
611
+ }
612
+ pushedLocaleHeadersPerKey.get(pushedKeyLower).add(pushedHeader.toLowerCase());
613
+ }
614
+ }
615
+ }
616
+ }
592
617
  for (const locale of Object.keys(changes)) {
593
618
  if (!changes[locale]?.[sheetTitle]) continue;
594
619
  const localeData = changes[locale][sheetTitle];
@@ -631,6 +656,35 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
631
656
  }
632
657
  if (localeHeader) {
633
658
  row.set(localeHeader, String(localeData[key]));
659
+ if (autoTranslate) {
660
+ const sourceHeaderLower = localeHeader.toLowerCase();
661
+ const sourceHeaderIndex = headerRow.indexOf(sourceHeaderLower);
662
+ if (sourceHeaderIndex >= 0) {
663
+ const sourceColumnLetter = columnIndexToLetter(sourceHeaderIndex);
664
+ const rowObj = row.toObject();
665
+ const pushedHeaders = pushedLocaleHeadersPerKey.get(keyLower) ?? /* @__PURE__ */ new Set();
666
+ for (const targetLocaleHeader of locales) {
667
+ const targetLower = targetLocaleHeader.toLowerCase();
668
+ if (targetLower === sourceHeaderLower) continue;
669
+ if (pushedHeaders.has(targetLower)) continue;
670
+ const targetHeaderIndex = headerRow.indexOf(targetLower);
671
+ if (targetHeaderIndex < 0) continue;
672
+ const exactTargetHeader = originalHeaders.find(
673
+ (h) => h.toLowerCase() === targetLower
674
+ );
675
+ if (!exactTargetHeader) continue;
676
+ const existingValue = rowObj[exactTargetHeader];
677
+ const isEmpty = !existingValue || existingValue.toString().trim() === "";
678
+ if (isEmpty || override) {
679
+ const targetColumnLetter = columnIndexToLetter(targetHeaderIndex);
680
+ row.set(
681
+ exactTargetHeader,
682
+ `=GOOGLETRANSLATE(INDIRECT("${sourceColumnLetter}"&ROW());$${sourceColumnLetter}$1;${targetColumnLetter}$1)`
683
+ );
684
+ }
685
+ }
686
+ }
687
+ }
634
688
  try {
635
689
  await withRetry(
636
690
  () => row.save(),
@@ -779,19 +833,23 @@ function readDataJson(dataJsonPath) {
779
833
  }
780
834
 
781
835
  // src/utils/syncManager.ts
782
- async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}) {
836
+ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}, override = false, cleanPush = false) {
783
837
  const result = {
784
838
  shouldRefresh: false,
785
839
  hasChanges: false
786
840
  };
787
841
  const localData = readDataJson(dataJsonPath);
788
842
  const dataJsonExists = localData !== null;
789
- const shouldSyncToSheet = syncLocalChanges && dataJsonExists && isDataJsonNewer(dataJsonPath, translationsOutputDir);
843
+ const shouldSyncToSheet = dataJsonExists && (cleanPush || syncLocalChanges && isDataJsonNewer(dataJsonPath, translationsOutputDir));
790
844
  if (!shouldSyncToSheet || !localData) {
791
845
  return result;
792
846
  }
793
- console.log("Local languageData.json is newer than translation files. Checking for changes...");
794
- const changes = findLocalChanges(localData, spreadsheetData);
847
+ if (cleanPush) {
848
+ console.log("Clean push enabled \u2013 pushing ALL keys from languageData.json to the spreadsheet...");
849
+ } else {
850
+ console.log("Local languageData.json is newer than translation files. Checking for changes...");
851
+ }
852
+ const changes = cleanPush ? localData : findLocalChanges(localData, spreadsheetData);
795
853
  const hasChanges = Object.keys(changes).length > 0 && Object.keys(changes).some(
796
854
  (locale) => Object.keys(changes[locale]).length > 0
797
855
  );
@@ -801,9 +859,10 @@ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir,
801
859
  }
802
860
  const localesCount = Object.keys(changes).length;
803
861
  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.`);
862
+ const pushMode = cleanPush ? "clean push" : "incremental sync";
863
+ console.log(`Found local changes (${pushMode}): ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
805
864
  try {
806
- await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping);
865
+ await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping, override);
807
866
  result.shouldRefresh = true;
808
867
  result.hasChanges = true;
809
868
  } catch (err) {
@@ -1132,7 +1191,9 @@ async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
1132
1191
  config.autoTranslate,
1133
1192
  finalTranslations,
1134
1193
  config.waitSeconds,
1135
- globalLocaleMapping
1194
+ globalLocaleMapping,
1195
+ config.override,
1196
+ config.cleanPush
1136
1197
  );
1137
1198
  if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
1138
1199
  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
 
@@ -594,7 +598,7 @@ function columnIndexToLetter(index) {
594
598
  } while (i >= 0);
595
599
  return result;
596
600
  }
597
- async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}) {
601
+ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate = false, localeMapping = {}, override = false) {
598
602
  console.log("Updating spreadsheet with local changes...");
599
603
  const baseDelayMs = waitSeconds * 1e3;
600
604
  for (const sheetTitle of new Set(
@@ -654,6 +658,27 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
654
658
  });
655
659
  const newKeys = /* @__PURE__ */ new Map();
656
660
  const keyLocalesMap = /* @__PURE__ */ new Map();
661
+ const pushedLocaleHeadersPerKey = /* @__PURE__ */ new Map();
662
+ if (autoTranslate) {
663
+ for (const pushedLocale of Object.keys(changes)) {
664
+ if (!changes[pushedLocale]?.[sheetTitle]) continue;
665
+ for (const pushedKey of Object.keys(changes[pushedLocale][sheetTitle])) {
666
+ const pushedKeyLower = pushedKey.toLowerCase();
667
+ if (!existingKeys.has(pushedKeyLower)) continue;
668
+ let pushedHeader = getOriginalHeaderForLocale(pushedLocale, localeMapping);
669
+ if (!pushedHeader) {
670
+ const prefix = getLanguagePrefix(pushedLocale);
671
+ pushedHeader = originalHeaders.find((h) => getLanguagePrefix(h) === prefix);
672
+ }
673
+ if (pushedHeader) {
674
+ if (!pushedLocaleHeadersPerKey.has(pushedKeyLower)) {
675
+ pushedLocaleHeadersPerKey.set(pushedKeyLower, /* @__PURE__ */ new Set());
676
+ }
677
+ pushedLocaleHeadersPerKey.get(pushedKeyLower).add(pushedHeader.toLowerCase());
678
+ }
679
+ }
680
+ }
681
+ }
657
682
  for (const locale of Object.keys(changes)) {
658
683
  if (!changes[locale]?.[sheetTitle]) continue;
659
684
  const localeData = changes[locale][sheetTitle];
@@ -696,6 +721,35 @@ async function updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, auto
696
721
  }
697
722
  if (localeHeader) {
698
723
  row.set(localeHeader, String(localeData[key]));
724
+ if (autoTranslate) {
725
+ const sourceHeaderLower = localeHeader.toLowerCase();
726
+ const sourceHeaderIndex = headerRow.indexOf(sourceHeaderLower);
727
+ if (sourceHeaderIndex >= 0) {
728
+ const sourceColumnLetter = columnIndexToLetter(sourceHeaderIndex);
729
+ const rowObj = row.toObject();
730
+ const pushedHeaders = pushedLocaleHeadersPerKey.get(keyLower) ?? /* @__PURE__ */ new Set();
731
+ for (const targetLocaleHeader of locales) {
732
+ const targetLower = targetLocaleHeader.toLowerCase();
733
+ if (targetLower === sourceHeaderLower) continue;
734
+ if (pushedHeaders.has(targetLower)) continue;
735
+ const targetHeaderIndex = headerRow.indexOf(targetLower);
736
+ if (targetHeaderIndex < 0) continue;
737
+ const exactTargetHeader = originalHeaders.find(
738
+ (h) => h.toLowerCase() === targetLower
739
+ );
740
+ if (!exactTargetHeader) continue;
741
+ const existingValue = rowObj[exactTargetHeader];
742
+ const isEmpty = !existingValue || existingValue.toString().trim() === "";
743
+ if (isEmpty || override) {
744
+ const targetColumnLetter = columnIndexToLetter(targetHeaderIndex);
745
+ row.set(
746
+ exactTargetHeader,
747
+ `=GOOGLETRANSLATE(INDIRECT("${sourceColumnLetter}"&ROW());$${sourceColumnLetter}$1;${targetColumnLetter}$1)`
748
+ );
749
+ }
750
+ }
751
+ }
752
+ }
699
753
  try {
700
754
  await withRetry(
701
755
  () => row.save(),
@@ -844,19 +898,23 @@ function readDataJson(dataJsonPath) {
844
898
  }
845
899
 
846
900
  // src/utils/syncManager.ts
847
- async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}) {
901
+ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir, syncLocalChanges, autoTranslate, spreadsheetData, waitSeconds, localeMapping = {}, override = false, cleanPush = false) {
848
902
  const result = {
849
903
  shouldRefresh: false,
850
904
  hasChanges: false
851
905
  };
852
906
  const localData = readDataJson(dataJsonPath);
853
907
  const dataJsonExists = localData !== null;
854
- const shouldSyncToSheet = syncLocalChanges && dataJsonExists && isDataJsonNewer(dataJsonPath, translationsOutputDir);
908
+ const shouldSyncToSheet = dataJsonExists && (cleanPush || syncLocalChanges && isDataJsonNewer(dataJsonPath, translationsOutputDir));
855
909
  if (!shouldSyncToSheet || !localData) {
856
910
  return result;
857
911
  }
858
- console.log("Local languageData.json is newer than translation files. Checking for changes...");
859
- const changes = findLocalChanges(localData, spreadsheetData);
912
+ if (cleanPush) {
913
+ console.log("Clean push enabled \u2013 pushing ALL keys from languageData.json to the spreadsheet...");
914
+ } else {
915
+ console.log("Local languageData.json is newer than translation files. Checking for changes...");
916
+ }
917
+ const changes = cleanPush ? localData : findLocalChanges(localData, spreadsheetData);
860
918
  const hasChanges = Object.keys(changes).length > 0 && Object.keys(changes).some(
861
919
  (locale) => Object.keys(changes[locale]).length > 0
862
920
  );
@@ -866,9 +924,10 @@ async function handleBidirectionalSync(doc, dataJsonPath, translationsOutputDir,
866
924
  }
867
925
  const localesCount = Object.keys(changes).length;
868
926
  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.`);
927
+ const pushMode = cleanPush ? "clean push" : "incremental sync";
928
+ console.log(`Found local changes (${pushMode}): ${localesCount} locale(s), ~${keysCount} key(s) to sync to the spreadsheet.`);
870
929
  try {
871
- await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping);
930
+ await updateSpreadsheetWithLocalChanges(doc, changes, waitSeconds, autoTranslate, localeMapping, override);
872
931
  result.shouldRefresh = true;
873
932
  result.hasChanges = true;
874
933
  } catch (err) {
@@ -1197,7 +1256,9 @@ async function getSpreadSheetData(_docTitle, options = {}, _refreshDepth = 0) {
1197
1256
  config.autoTranslate,
1198
1257
  finalTranslations,
1199
1258
  config.waitSeconds,
1200
- globalLocaleMapping
1259
+ globalLocaleMapping,
1260
+ config.override,
1261
+ config.cleanPush
1201
1262
  );
1202
1263
  if (syncResult.shouldRefresh && _refreshDepth < MAX_SYNC_REFRESH_DEPTH) {
1203
1264
  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"}
@@ -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.0",
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",