Integration
@@ -43,6 +43,7 @@
+
@@ -192,6 +193,11 @@
unit.remove();
}
+ function csvEscape(value) {
+ const text = String(value ?? '');
+ return '"' + text.replaceAll('"', '""') + '"';
+ }
+
function escapeHtml(value) {
return String(value)
.replaceAll('&', '&')
@@ -222,6 +228,7 @@
const genericSourceSelect = host.querySelector('#salesforce-translation-import-generic-source-select');
const analyzeBtn = host.querySelector('#salesforce-translation-import-analyze-btn');
const exportBtn = host.querySelector('#salesforce-translation-import-export-btn');
+ const extractBtn = host.querySelector('#salesforce-translation-import-extract-btn');
const sourceStatus = host.querySelector('#salesforce-translation-import-source-status');
const targetStatus = host.querySelector('#salesforce-translation-import-target-status');
const statsNode = host.querySelector('#salesforce-translation-import-stats');
@@ -434,6 +441,64 @@
});
}
+ function collectExtractionRows() {
+ const rows = [];
+
+ state.sourceFiles
+ .filter((source) => !source.error)
+ .forEach((source) => {
+ const xml = parseXml(source.text);
+ const units = Array.from(xml.getElementsByTagName('trans-unit'));
+
+ units.forEach((unit) => {
+ const details = getUnitDetails(unit);
+
+ if (!details) {
+ return;
+ }
+
+ const sourceNode = unit.getElementsByTagName('source')[0];
+ const targetNode = unit.getElementsByTagName('target')[0];
+
+ rows.push({
+ object: details.objectName,
+ field: details.fieldName,
+ target: targetNode ? targetNode.textContent ?? '' : '',
+ language: source.languageLabel,
+ source: sourceNode ? sourceNode.textContent ?? '' : '',
+ file: source.name
+ });
+ });
+ });
+
+ return rows;
+ }
+
+ function downloadCsv(filename, rows) {
+ const header = ['object', 'field', 'target', 'language', 'source', 'file'];
+ const lines = [
+ header.map(csvEscape).join(','),
+ ...rows.map((row) => [
+ row.object,
+ row.field,
+ row.target,
+ row.language,
+ row.source,
+ row.file
+ ].map(csvEscape).join(','))
+ ];
+
+ const blob = new Blob(["\uFEFF" + lines.join('\n')], { type: 'text/csv;charset=utf-8' });
+ const link = document.createElement('a');
+ const downloadUrl = URL.createObjectURL(blob);
+
+ link.href = downloadUrl;
+ link.download = filename;
+ link.click();
+
+ window.setTimeout(() => URL.revokeObjectURL(downloadUrl), 1000);
+ }
+
function genericSourceSelectionIsMissing() {
return Boolean(state.targetFileName) &&
!state.targetHasLanguageColumn &&
@@ -798,6 +863,24 @@
window.setTimeout(() => URL.revokeObjectURL(downloadUrl), 1000);
}
+ async function extractCsv() {
+ await state.sourceLoadPromise;
+
+ if (state.sourceFiles.filter((entry) => !entry.error).length === 0) {
+ window.alert('Select at least one valid Salesforce XLIFF source file.');
+ return;
+ }
+
+ const rows = collectExtractionRows();
+
+ if (rows.length === 0) {
+ window.alert('No translatable Salesforce rows were found in the selected XLIFF files.');
+ return;
+ }
+
+ downloadCsv('salesforce_translation_template.csv', rows);
+ }
+
xmlInput.addEventListener('change', () => {
state.sourceLoadPromise = loadSourceFiles();
});
@@ -808,6 +891,7 @@
});
analyzeBtn.addEventListener('click', analyze);
exportBtn.addEventListener('click', exportZip);
+ extractBtn.addEventListener('click', extractCsv);
renderFileStatus();
renderPreview();