Skip to content

Localization

Three props control language and layout, and each does one job. translations changes the words. locale picks plural forms. rtl flips the layout. Set them independently.

TypeDataEditorTranslations

Override any UI string. Pass a partial object — only the keys you provide are replaced.

This is the only prop that changes the language. Setting locale alone leaves the UI in English.

<DataEditor
translations={{
dataEditor: {
modal: {
editTitle: "Edit Employees",
importTitle: "Import Employee Data",
},
footer: {
submit: "Save Changes",
},
},
}}
...
/>

Every key lives under dataEditor. Pass any subset — only the keys you provide are replaced.

{
"dataEditor": {
"modal": {
"importTitle": "Import Data",
"editTitle": "Edit Data",
"viewTitle": "View Data"
},
"confirmClose": {
"title": "Discard changes?",
"text": "You have unsaved changes. Are you sure you want to close?",
"action": "Discard"
},
"confirmSubmit": {
"title": "Confirm submission",
"text": "You are about to submit the following changes:",
"createRows_one": "{{count}} new row will be created",
"createRows_other": "{{count}} new rows will be created",
"updateRows_one": "{{count}} row will be updated",
"updateRows_other": "{{count}} rows will be updated",
"deleteRows_one": "{{count}} row will be deleted",
"deleteRows_other": "{{count}} rows will be deleted",
"bannerTitle_one": "{{count}} row has errors",
"bannerTitle_other": "{{count}} rows have errors",
"action": "Submit"
},
"footer": {
"submit": "Submit",
"submitBlockedByErrors": "Fix errors before submitting",
"import": "Import",
"next": "Next",
"cancel": "Cancel",
"back": "Back",
"export": "Export",
"exportAll": "Export all",
"exportFiltered": "Export filtered",
"csvFormat": "Comma-separated values (.csv)",
"tsvFormat": "Tab-separated values (.tsv)",
"excelFormat": "Microsoft Excel (.xlsx)",
"jsonFormat": "JSON (.json)",
"xmlFormat": "XML (.xml)"
},
"statusBar": {
"totalRows": "{{total}} rows",
"filteredRows": "{{filtered}} of {{total}} rows"
},
"toast": {
"dismiss": "Dismiss",
"rowMayNotBeVisible": "Row has been added but may not be visible due to active filters or sorting"
},
"grid": {
"emptyTitle": "No data",
"emptyText": "Import data or add rows manually",
"loading": "Loading data...",
"emptyCell": "Empty",
"a11y": {
"gridLabel": "Data editor",
"cellFocus": "Row {{row}}, {{column}}: {{value}}",
"cellFocusEmpty": "Row {{row}}, {{column}}: empty",
"selectAll": "All cells selected",
"rowsSelected": "{{count}} rows selected",
"columnsSelected": "{{count}} columns selected"
},
"contextMenu": {
"cut": "Cut",
"cutCells": "Cut ({{count}})",
"copy": "Copy",
"copyCells": "Copy ({{count}})",
"paste": "Paste",
"deleteRow": "Delete row",
"deleteRows": "Delete rows ({{count}})",
"restoreRow": "Restore row",
"restoreRows": "Restore rows ({{count}})",
"sortAsc": "Sort A to Z",
"sortDesc": "Sort Z to A",
"sortRemove": "Remove sorting",
"insertAbove": "Insert row above",
"insertBelow": "Insert row below",
"duplicateRow": "Duplicate row",
"cutRow": "Cut row",
"cutRows": "Cut rows ({{count}})",
"copyRow": "Copy row",
"copyRows": "Copy rows ({{count}})",
"clearRow": "Clear row",
"clearRows": "Clear rows ({{count}})",
"clearAll": "Clear all",
"pin": "Pin column",
"pinColumns": "Pin columns",
"unpin": "Unpin column",
"unpinColumns": "Unpin columns",
"cutColumn": "Cut column",
"copyColumn": "Copy column",
"pasteColumn": "Paste column",
"lockColumn": "Lock column",
"lockColumns": "Lock columns",
"lockedCannotClear": "Can't clear a locked column",
"lockedCannotDelete": "Can't delete a locked column",
"lockedCannotRevert": "Can't revert a locked column",
"lockedCannotUnlock": "This column was locked by configuration",
"unlockColumn": "Unlock column",
"unlockColumns": "Unlock columns",
"clearColumn": "Clear column",
"clearColumns": "Clear columns",
"deleteColumn": "Delete column",
"deleteColumns": "Delete columns",
"editColumn": "Edit column",
"transform": "Transform",
"transformMerge": "Merge",
"transformSplit": "Split",
"formula": "Formula",
"lockedCannotFormula": "Can't apply a formula to a locked column",
"revertChanges": "Revert changes",
"markAsCorrect": "Mark as correct"
},
"formulaModal": {
"title": "Apply formula",
"apply": "Apply",
"applyToRows_one": "Apply to {{count}} row",
"applyToRows_other": "Apply to {{count}} rows",
"inputLabel": "Formula",
"placeholder": "=UPPER(value) · Type @ to browse",
"groupFunctions": "Functions",
"groupColumns": "Columns",
"groupKeywords": "Keywords",
"keywordValue": "Current cell value",
"preview": "Preview",
"errors": {
"unexpected-character": "'{{char}}' isn't valid here",
"unexpected-escape": "Invalid escape '\\{{char}}' — only \\} and \\\\ are allowed inside @{}",
"unterminated-column-ref": "@{...} isn't closed — add a closing }",
"expected-equals": "Formulas must start with =",
"expected-expression": "Add a function, value, or @column after =",
"expected-open-paren": "Missing '(' after {{name}}",
"expected-close-paren": "Missing closing ')'",
"expected-column-name": "Add a column name after @ — e.g. @Name or @{First Name}",
"unexpected-token": "'{{token}}' isn't expected here",
"unknown-function": "No function named '{{name}}'",
"unknown-column": "No column named '{{name}}'",
"arity-mismatch-too-few": "{{name}} expects at least {{min}} arguments — got {{actual}}",
"arity-mismatch-too-many": "{{name}} takes at most {{max}} arguments — got {{actual}}",
"function-not-in-expression-mode": "'{{name}}' can't be used here — use Merge or Split from the Transform menu",
"column-not-numeric": "'{{name}}' is not a number column — arithmetic requires number columns"
}
},
"formulas": {
"UPPER": {
"label": "Uppercase"
},
"LOWER": {
"label": "Lowercase"
},
"TRIM": {
"label": "Trim whitespace"
},
"CAPITALIZE": {
"label": "Capitalize"
},
"ROUND": {
"label": "Round"
},
"ROUND_UP": {
"label": "Round up"
},
"ROUND_DOWN": {
"label": "Round down"
},
"ABS": {
"label": "Absolute value"
},
"CLEAR": {
"label": "Clear"
},
"CONCAT": {
"label": "Concatenate"
},
"LEFT": {
"label": "Left"
},
"RIGHT": {
"label": "Right"
},
"MID": {
"label": "Mid"
},
"SUBSTITUTE": {
"label": "Substitute"
},
"MERGE": {
"label": "Merge columns"
},
"SPLIT": {
"label": "Split column"
}
},
"transformMerge": {
"addColumn": "Add column",
"apply": "Apply",
"deleteSource": "Delete source columns",
"deleteSourceDescription": "Columns added during import can be deleted. Schema columns will remain.",
"from": "From",
"into": "Into",
"joinWith": "Join with",
"joinWithPlaceholder": "e.g. space, comma",
"preview": "Preview",
"removeColumn": "Remove column",
"applyToRows_one": "Apply to {{count}} row",
"applyToRows_other": "Apply to {{count}} rows",
"selectColumn": "Select column",
"title": "Merge"
},
"transformSplit": {
"addColumn": "Add column",
"apply": "Apply",
"applyToRows_one": "Apply to {{count}} row",
"applyToRows_other": "Apply to {{count}} rows",
"deleteSource": "Delete source column",
"deleteSourceDescription": "Columns added during import can be deleted. Schema columns will remain.",
"from": "From",
"into": "Into",
"preview": "Preview",
"removeColumn": "Remove column",
"selectColumn": "Select column",
"splitBy": "Split by",
"splitByPlaceholder": "e.g. space, comma",
"title": "Split"
},
"phase": {
"splitting": "Splitting columns...",
"merging": "Merging columns...",
"pasting": "Pasting data...",
"clearing": "Clearing cells...",
"filling": "Filling cells...",
"sorting": "Sorting rows...",
"undoing": "Reverting changes...",
"redoing": "Reapplying changes...",
"deleting": "Deleting rows...",
"deletingSource": "Removing data source...",
"importing": "Importing data...",
"transforming": "Transforming...",
"default": "Processing..."
}
},
"dataSources": {
"title": "Data Sources",
"importData": "Import data",
"addRow": "Add row",
"manuallyAdded": "Manually added",
"existingData": "Existing data",
"addDataSource": "Add data source",
"show": "Show",
"hide": "Hide",
"remove": "Remove",
"confirmRemove": {
"title": "Remove data source?",
"text": "All data imported from this source will be removed.",
"action": "Remove"
}
},
"filters": {
"title": "Filters",
"search": "Search",
"replace": "Replace",
"findAndReplace": "Find & Replace",
"searchMode": "Search mode",
"matchCase": "Match case",
"matchEntireCell": "Match entire cell",
"rows": "Rows",
"columns": "Columns",
"searchInColumns": "Search in columns",
"allColumns": "All columns",
"rowsWithErrors": "Rows with errors",
"editedRows": "Changed rows",
"newRows": "New rows",
"rowsWithEmptyCells": "Rows with empty cells",
"rowsWithMisplacedValues": "Rows with misplaced values",
"deletedRows": "Deleted rows",
"previousOccurrence": "Previous occurrence",
"nextOccurrence": "Next occurrence",
"zeroResults": "No results found",
"allValues": "All values",
"min": "Min",
"max": "Max",
"from": "From",
"to": "To",
"replaceAll": "Replace all",
"resetFilters": "Reset filters",
"showMore": "View error details",
"showLess": "Hide error details"
},
"undoRedo": {
"undo": "Undo",
"redo": "Redo"
},
"validation": {
"alreadyExists": "Already exists in your database",
"endDateBeforeStart": "End date must be after start date",
"invalidDate": "Invalid date",
"invalidEmail": "Invalid email address",
"invalidFormat": "Invalid format",
"invalidNumber": "Invalid number",
"invalidOption": "Invalid option",
"outOfRange": "Out of range",
"required": "This field is required",
"structuralMismatch": "This might be in the wrong column.",
"valueMustBeUnique": "Value must be unique"
},
"license": {
"loading": "Loading data editor"
},
"connecting": {
"label": "Connecting to server…"
},
"errors": {
"RENDER_ERROR": {
"title": "Something went wrong",
"text": "Please close this window and try again"
},
"license": {
"invalid": {
"title": "Invalid license",
"text": "Please contact support for assistance."
},
"missing": {
"title": "Missing API key",
"text": "No API key was provided. Please configure a valid API key."
},
"domain_not_allowed": {
"title": "Domain not allowed",
"text": "This domain is not authorized for this license. Please check your domain settings."
},
"subscription_inactive": {
"title": "Subscription inactive",
"text": "Your subscription is no longer active. Please renew to continue."
}
},
"scale": {
"bootstrap_failed": {
"title": "Couldn't connect to the server",
"text": "The server returned an error. Please refresh the page or contact support."
},
"workspace_lost": {
"title": "Connection lost",
"text": "The session ended unexpectedly. Refresh the page to reconnect."
},
"unreachable": {
"title": "Server unreachable",
"text": "Check your connection and refresh the page."
},
"server_error": {
"title": "Server error",
"text": "The server returned an error. Please refresh the page or contact support."
}
}
},
"uploader": {
"steps": {
"selectFiles": "Select files",
"headerSelection": "Header selection",
"matchColumns": "Match columns",
"matchValues": "Match values",
"primaryKey": "Primary key"
},
"uploadFile": {
"parseError": "Failed to parse file",
"clickToUpload": "Click to upload",
"orDragAndDrop": "or drag and drop",
"formats": "CSV, TSV, XLSX, JSON, XML",
"csvWarning_one": "{{count}} row had formatting issues (row {{rows}})",
"csvWarning_other": "{{count}} rows had formatting issues (rows {{rows}})",
"downloadExample": "Download sample file",
"fileTooLarge": "The file is too large to process",
"reset": "Reset",
"uploading": "Uploading file"
},
"remoteSources": {
"browseFile": "Browse file",
"emptyData": "The source returned no data",
"fetchError": "Failed to load data"
},
"headerSelection": {
"noHeaderLabel": "My data has no header row"
},
"matchColumns": {
"allMatched": "All columns are matched",
"banner": "Some columns could not be automatically matched",
"importedColumns": "Imported columns",
"matchedCount": "{{matched}}/{{total}} matched",
"targetColumns": "Target columns",
"selectColumnPlaceholder": "Select column",
"showMatched": "Show matched",
"syntheticColumn": "C{{index}}",
"syntheticColumnValue": "C{{index}}: {{value}}",
"bestMatch": "Best match",
"createColumn": "Create column",
"createColumnNameLabel": "Column name",
"createColumnNamePlaceholder": "Enter column name",
"createColumnNameTaken": "A column with this name already exists",
"createColumnSubmit": "Create",
"createColumnTitle": "Create column",
"editColumnSubmit": "Save",
"editColumnTitle": "Edit column",
"createColumnWarning": "A matching column already exists",
"newColumnTag": "New",
"unmatchedWarning": "Unmatched columns won't be imported. Match this column to keep the data. You can transform columns after importing."
},
"sheetPreview": {
"rowCount": "{{count}} rows",
"emptySheet": "Empty sheet"
},
"matchValues": {
"importedValues": "Imported values",
"matchedCount": "{{matched}}/{{total}} matched",
"targetValue": "Target value",
"selectValuePlaceholder": "Select value",
"showAll": "Show all",
"showMatched": "Show matched",
"allMatched": "All values are matched",
"tooManyValues": "Showing first {{shown}} of {{total}} values",
"unmatchedWarning": "Unmatched values won't be imported. Match this value to keep the data. You can edit values after importing.",
"createAllOptions": "Create all options",
"createOption": "Create option",
"createOptionTitle": "Create option",
"createOptionNameLabel": "Option name",
"createOptionNamePlaceholder": "Enter option name",
"createOptionNameTaken": "This option already exists",
"createOptionSubmit": "Create",
"reapplySeparator": "Reset to auto-detected separator",
"separator": "Separator",
"separatedBy": "Values separated by"
},
"primaryKey": {
"none": "No primary key",
"noneHint": "All rows will be appended as new entries without deduplication."
}
},
"chat": {
"emptyTitle": "What would you like to fix?",
"header": "Chat with AI",
"placeholder": "Ask AI...",
"send": "Send"
},
"common": {
"cancel": "Cancel",
"collapse": "Collapse",
"dropToImport": "Drop file to upload",
"expand": "Expand",
"remove": "Remove",
"save": "Save",
"search": "Search"
}
}
}
Typestring
Default"en"

BCP 47 locale tag, for example "en", "fr", or "ar". It selects the plural form for keys that end in _zero, _one, _two, _few, _many, or _other, using Intl.PluralRules. When no key matches the selected category, the SDK falls back to _other. An invalid tag falls back to "en".

That is the whole job. locale does not load translations, does not switch the language, and does not affect how imported dates and numbers are parsed. Date and number detection reads the browser locale instead.

Set it when your language has plural rules that differ from English. Arabic has six forms, Russian has three, Japanese has one.

<DataEditor locale="ar" translations={arabicTranslations} ... />
Typeboolean
Defaultfalse

Enable right-to-left layout. Set to true for Arabic, Hebrew, and other RTL languages. Affects grid direction, text alignment, and scrollbar position. Exports to CSV, TSV, and XLSX also write the columns in reverse order, so the first column lands on the right.

rtl is independent of locale. Setting one does not set the other.

<DataEditor locale="ar" rtl={true} translations={arabicTranslations} ... />