Ballmac UI home

Docs

Translating Ballmac UI (i18n)

Every built-in label, placeholder and screen reader text is a message with an English default. One provider translates all 467 of them and sets the locale for dates and numbers.

Quick start

npx shadcn@latest add @ballmac/i18n
app/layout.tsx
import { I18nProvider } from "@/lib/ballmac/i18n"
import ar from "@/messages/ar.json"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ar" dir="rtl">
      <body>
        <I18nProvider locale="ar" messages={ar}>
          {children}
        </I18nProvider>
      </body>
    </html>
  )
}

messages is a flat object from key to text. Anything you leave out stays in English, so you can translate in stages. Download the complete list of keys with their English text from /i18n/en.json, copy it to ar.json, and translate the values.

Placeholders and plurals

messages/ar.json
{
  "pagination.nextPage": "الصفحة التالية",
  "data-table.pageOf": "الصفحة {page} من {total}",
  "workspace-card.members_one": "عضو واحد",
  "workspace-card.members_two": "عضوان",
  "workspace-card.members_few": "{count} أعضاء",
  "workspace-card.members_many": "{count} عضوًا",
  "workspace-card.members_other": "{count} عضو"
}

{name} is replaced with a value. Where a message depends on a number, add one key per plural category your language has (_zero, _one, _two, _few, _many, _other, chosen with Intl.PluralRules); English needs only _one and _other, which are built in.

Locale: dates, numbers and money

The provider's locale is used by every component that formats a number, a date, a currency or a duration. Without a provider, <html lang> is used, then en-US. A locale prop on a single component always wins. To get Western digits in an Arabic UI, use ar-u-nu-latn.

Your own components

"use client"
import { useLocale, useMessages } from "@/lib/ballmac/i18n"

export function Greeting({ name }: { name: string }) {
  const msg = useMessages()
  return <p>{msg("app.greeting", "Welcome back, {name}", { name })}</p>
}

msg.rich fills placeholders with React nodes (for example a <kbd>). If you already use next-intl, i18next or Lingui, keep them for your app and pass their output to I18nProvider as messages.

What is translated, and what is not

  • All components: accessible names, placeholders, hidden text, default button and empty-state text, status words and templated sentences.
  • Props still win. closeLabel, emptyMessage, label and similar props override the dictionary.
  • Blocks and templates are copy-in starting points. Their headlines and sample copy are props or live in the file, so you edit them as content. The right-to-left layout is covered in RTL.
  • Sample values (such as the .env placeholder) and brand names are not messages.

All 467 messages

467 of 467 messages

KeyEnglish
activity-feed.emptyMessageNo activity yet
agent-plan.progress{title} progress
agent-plan.retryRetry
agent-plan.titlePlan
ai-chat.labelConversation
ai-chat.scrollButtonLabelScroll to latest message
ai-chat.suggestionsSuggestions
ai-message.labelCopy message
ai-message.messageActionsMessage actions
api-endpoint.defaultValueDefault: {value}
api-endpoint.parameters{group} parameters
api-endpoint.requestAndResponsesRequest and responses
api-key-field.copiedCopied
api-key-field.copyKeyCopy key
api-key-field.hideKeyHide key
api-key-field.labelAPI key
api-key-field.regenerateKeyRegenerate key
api-key-field.showKeyShow key
app-shell.labelSidebar
app-shell.label2Details
app-shell.navigationNavigation
app-shell.openNavigationOpen navigation
approval-card.alwaysAllowLabelAlways allow
approval-card.approveLabelApprove
approval-card.deniesItselfInDenies itself in {seconds}s
approval-card.denyLabelDeny
approval-card.previewLabelExactly what will run
artifact-panel.closeClose
artifact-panel.closeArtifactClose artifact
artifact-panel.copiedCopied
artifact-panel.copyCodeCopy code
artifact-panel.downloadDownload
artifact-panel.downloadFileDownload {name}
artifact-panel.filefile
artifact-panel.nextVersionNext version
artifact-panel.previousVersionPrevious version
artifact-panel.versionOfof {total}
artifact-panel.versionsVersions
artifact-panel.viewView
audio-player.audioPlayerAudio player: {title}
audio-player.backSecondsBack {back} seconds
audio-player.chapterChapter:
audio-player.forwardSecondsForward {forward} seconds
audio-player.pausePause
audio-player.playPlay
audio-player.playbackSpeedChangeSpeedPlayback speed {rate}×. Change speed
audio-player.seekSeek
avatar-circles.andMoreand {extra} more
avatar.more{count} more
back-to-top.labelBack to top
banner.dismissDismiss {title}
billing-card.cancelSubscriptionCancel subscription
billing-card.changePlanChange plan
billing-card.currentPlanCurrent plan
billing-card.downloadInvoiceDownload invoice {id}
billing-card.expExp {date}
billing-card.paymentMethodPayment method
billing-card.recentInvoicesRecent invoices
billing-card.seatsSeats
billing-card.seatsOf{used} of {total} used
billing-card.seatsUsedSeats used
billing-card.updateUpdate
breadcrumb.labelBreadcrumb
breadcrumb.morePagesMore pages
browser-frame.secureConnectionSecure connection
calendar-agenda.agendaAgenda
calendar-agenda.chooseDateChoose date
calendar-agenda.emptyMessageNo events scheduled
calendar-agenda.nextDayNext day
calendar-agenda.previousDayPrevious day
carousel.chooseSlideChoose slide
carousel.goToSlideGo to slide {n}
carousel.labelCarousel
carousel.nextSlideNext slide
carousel.pauseAutoplayPause autoplay
carousel.previousSlidePrevious slide
carousel.startAutoplayStart autoplay
changelog-feed.allAll
changelog-feed.filterChangesFilter changes
changelog-feed.latestLatest
changelog-feed.noReleasesMatchThisFilterNo releases match this filter.
chat-attachment.labelAttachments
chat-attachment.openOpen {name}
chat-attachment.removeRemove {name}
chat-attachment.retryRetry
chat-attachment.retryUploadingRetry uploading {name}
chat-attachment.uploadingUploading {name}
chat-attachment.uploadingEllipsisUploading…
chat-attachment.uploadingPercentUploading {percent}%
citation.nextSourceNext source
citation.openSourceOpen source
citation.previousSourcePrevious source
citation.sourceOfSource {n} of {total}
code-block.copiedCopied
code-block.filesFiles
code-block.labelCopy code
code-block.wrapLinesWrap lines
color-picker.chooseChoose {label}
color-picker.hexColorHex color
color-picker.hexValue{label} hex value
color-picker.labelColor
combobox.clearSelectionClear selection
combobox.emptyTextNo results found.
combobox.placeholderSelect an option
combobox.searchPlaceholderSearch
command-bar.allAll
command-bar.backBack
command-bar.closeClose
command-bar.currentPageCurrent page
command-bar.emptyTextNo results found.
command-bar.escEsc
command-bar.navigateNavigate
command-bar.placeholderSearch commands…
command-bar.selectSelect
command-bar.titleCommand bar
command.descriptionType a command or search. Use the arrow keys to move and Enter to run.
command.labelCommand menu
command.titleCommand menu
comparison-table.availableAvailable
comparison-table.featureFeature
comparison-table.notSpecifiedNot specified
comparison-table.unavailableUnavailable
contribution-graph.lessLess
contribution-graph.moreMore
contribution-graph.summary{label}: {total} total across 0 days
control-center.labelControl Center
control-center.nextTrackNext track
control-center.pausePause
control-center.playPlay
control-center.previousTrackPrevious track
cookie-consent.acceptAllAccept all
cookie-consent.alwaysOnAlways on
cookie-consent.backBack
cookie-consent.cookiePolicyCookie policy
cookie-consent.customizeCustomize
cookie-consent.descriptionWe use cookies to make the site work, understand how it is used and, with your permission, personalize content.
cookie-consent.rejectNonEssentialReject non-essential
cookie-consent.savePreferencesSave preferences
cookie-consent.titleWe value your privacy
copy-button.ariaLabelCopy to clipboard
copy-button.copiedLabelCopied
countdown.complete{label} complete
countdown.labelTime remaining
data-table.emptyMessageNo results.
data-table.nextPageNext page
data-table.pageOfPage {page} of {total}
data-table.previousPagePrevious page
data-table.searchSearch {label}
data-table.searchPlaceholderSearch
data-table.selectAllRowsSelect all rows on this page
data-table.selectRowSelect row {n}
data-table.showColumnsShow columns
date-picker.clearDateClear date
date-picker.placeholderPick a date
date-range-picker.fromFrom
date-range-picker.toTo
desktop-icons.labelDesktop
dialog.closeLabelClose
diff-viewer.diff{label} diff
diff-viewer.summary{added} added · {removed} removed
dotted-map.labelWorld map
env-editor.addVariableAdd variable
env-editor.cancelCancel
env-editor.hideValueOfHide value of {name}
env-editor.importImport
env-editor.keyKEY
env-editor.nameOfVariableName of variable {n}
env-editor.noVariablesYetNo variables yet
env-editor.pasteAEnvFilePaste a .env file
env-editor.pasteEnvPaste .env
env-editor.removeRemove {name}
env-editor.showValueOfShow value of {name}
env-editor.tipPasteSeveralLinesIntoTip: paste several lines into any name field to import them.
env-editor.titleEnvironment variables
env-editor.toFix{count} to fix
env-editor.valuevalue
env-editor.valueOfValue of {name}
env-editor.variableNvariable {n}
feedback-widget.tellUsMoreTell us more
feedback-widget.thankYouThank you
feedback-widget.topicTopic
feedback-widget.triggerLabelFeedback
feedback-widget.whatWorkedWellOrWhatWhat worked well, or what could be better?
feedback-widget.yourFeedbackHelpsUsImproveYour feedback helps us improve.
file-browser.clearClear
file-browser.deleteDelete
file-browser.downloadDownload
file-browser.filesFiles
file-browser.folderfolder
file-browser.folderPathFolder path
file-browser.rootLabelAll files
file-browser.rowLabel{name}, {detail}
file-browser.searchFilesSearch files
file-browser.selectSelect {name}
file-browser.selectAllFilesSelect all files
file-browser.selectedCount{count} selected
file-browser.selectionActionsSelection actions
file-browser.viewView
file-dropzone.chooseChoose
file-dropzone.dropFilesHereOrBrowseDrop files here or browse
file-dropzone.filesToUploadFiles to upload
file-dropzone.maxSize{size} MB each
file-dropzone.removeRemove {name}
file-dropzone.sizeKb{size} KB
file-tree.labelFiles
finder-window.asIconsas Icons
finder-window.asListas List
finder-window.backBack
finder-window.dateModifiedDate Modified
finder-window.documentdocument
finder-window.forwardForward
finder-window.itemLabel{name}, {kind}
finder-window.nameName
finder-window.pathPath
finder-window.searchSearch
finder-window.searchThisFolderSearch this folder
finder-window.sizeSize
finder-window.viewView
floating-nav.labelPrimary
git-graph.labelCommit history
git-graph.mergeMerge
globe.labelRotating globe
icon-cloud.labelItems
install-tabs.copiedCopied
install-tabs.copyCommandCopy command
install-tabs.packageManagerPackage manager
invite-members.descriptionThey will get an email with a link to join.
invite-members.emailAddressesEmail addresses
invite-members.nameCompanyComname@company.com
invite-members.pendingPending ({count})
invite-members.removeRemove {chip}
invite-members.resendInvitationToResend invitation to {email}
invite-members.revokeInvitationForRevoke invitation for {email}
invite-members.roleRole
invite-members.separateAddressesWithACommaSeparate addresses with a comma, space or Enter. You can paste a list.
invite-members.titleInvite teammates
json-viewer.collapseCollapse {name}
json-viewer.expandExpand {name}
json-viewer.labelJSON data
json-viewer.rootroot
kPress {key} to open
kanban-board.labelTask board
kanban-board.moveToNextColumnMove {title} to next column
kanban-board.moveToPreviousColumnMove {title} to previous column
kanban-board.useAltAndArrowKeys{title}, {column}. Use Alt and arrow keys to move.
keyboard-shortcuts.descriptionWork faster without leaving the keyboard.
keyboard-shortcuts.noShortcutMatchesNo shortcut matches “{query}”.
keyboard-shortcuts.pressPress {key} anywhere to open this list.
keyboard-shortcuts.searchPlaceholderSearch shortcuts
keyboard-shortcuts.titleKeyboard shortcuts
launchpad.labelLaunchpad
launchpad.noAppsMatchNo apps match “{query}”.
launchpad.pagePage {n}
launchpad.pageOfPage {n} of {pages}
launchpad.pagesPages
launchpad.searchSearch
launchpad.searchAppsSearch apps
lens.labelZoomable image
lens.moveThePointerOverIt{label}. Move the pointer over it, or use the arrow keys, to magnify. Escape hides the lens.
loading-dots.labelLoading
lock-screen.enterPasswordEnter Password
lock-screen.hintTouch ID or enter password
lock-screen.lockScreenLock screen
lock-screen.passwordForPassword for {name}
lock-screen.unlockUnlock
log-stream.clearClear
log-stream.emptyTextWaiting for output…
log-stream.filterFilter
log-stream.filterLogLinesFilter log lines
log-stream.lines{title}, {length} lines
log-stream.pauseStreamPause stream
log-stream.resumeStreamResume stream
log-stream.showLevelsShow levels
log-stream.titleLogs
log-stream.wrapLongLinesWrap long lines
mac-window.closeClose window
mac-window.minimizeMinimize window
mac-window.zoomZoom window
mega-menu.labelMain
mega-menu.learnMoreLearn more
model-picker.availableWithAvailable with {plan}
model-picker.contextTokens{size} tokens
model-picker.costHighHigh
model-picker.costLevel{level} cost
model-picker.costLowLow
model-picker.costMediumMedium
model-picker.higherPlana higher plan
model-picker.lockedLocked
model-picker.modelDetailsModel details
model-picker.newNew
model-picker.placeholderSelect a model
model-picker.searchPlaceholderSearch models…
multi-select.labelSelect options
multi-select.noMatchingOptionsNo matching options
multi-select.placeholderChoose options
multi-select.searchOptionsSearch options
multi-select.searchOptions2Search options…
multi-select.selected{count} selected
multi-select.selectedOf{count} selected of {max}
navbar.labelMain
navbar.label2Menu
navbar.siteNavigationSite navigation
notification-center.allNotificationsAll notifications
notification-center.dismissDismiss "{title}"
notification-center.emptyTextYou're all caught up.
notification-center.filterNotificationsFilter notifications
notification-center.labelNotifications
notification-center.markAllAsReadMark all as read
notification-center.markAsReadMark "{title}" as read
notification-center.unreadUnread
notification-center.unreadNotificationsUnread notifications
notification-stack.clearAllNotificationsClear all notifications
notification-stack.dismissLabelDismiss
notification-stack.labelNotifications
notification-stack.showAllNotificationsShow all {count} notifications
notification-stack.showLessShow less
number-input.decreaseDecrease {label}
number-input.increaseIncrease {label}
number-input.labelNumber
onboarding-checklist.completeMessageYou're all set. Nice work.
onboarding-checklist.descriptionFinish these steps to set up your workspace.
onboarding-checklist.dismissChecklistDismiss checklist
onboarding-checklist.markDone{title}: mark as done
onboarding-checklist.markNotDone{title}: mark as not done
onboarding-checklist.reviewTheStepsAgainReview the steps again
onboarding-checklist.titleGet started
package-badge.perWeek{count}/wk
package-badge.typesIncludedTypes included
pagination.labelPagination
pagination.morePagesMore pages
pagination.nextPageNext page
pagination.previousPagePrevious page
password-input.fairFair
password-input.goodGood
password-input.hidePasswordHide password
password-input.labelPassword
password-input.needsWorkNeeds work
password-input.showPasswordShow password
password-input.strengthHintStrength: {strength}. Use 8+ characters, mixed case, a number, and a symbol.
password-input.strongStrong
password-input.tooShortToo short
phone-input.countryDialingCodeCountry dialing code
phone-input.labelPhone number
plan-selector.billingPeriodBilling period
plan-selector.perMonth/ month
plan-selector.saveSave
popover.closeLabelClose popover
progress-steps.labelProgress
progress-steps.returnToReturn to {label}
prompt-input.attachmentsAttachments
prompt-input.labelAttach files
prompt-input.messageMessage
prompt-input.placeholderSend a message…
prompt-input.removeRemove {name}
prompt-input.stopLabelStop generating
prompt-input.submitLabelSend message
rating.clearClear
rating.labelRating
rating.ofStars{number} of {count} stars
resizable.labelResize panels
scroll-velocity.labelScrolling content
search-field.clearSearchClear search
search-field.labelSearch
section-tabs.labelSections
settings-panel.dirtyMessageYou have unsaved changes
settings-panel.discardDiscard
settings-panel.labelSettings
settings-panel.saveLabelSave changes
sheet.closeLabelClose
shortcut-hint.label{label}: {keys}
shortcut-hint.plus plus
sidebar.labelSidebar
sidebar.navigationNavigation
sidebar.toggleSidebarToggle sidebar
signature-pad.clearSignatureClear signature
signature-pad.drawDraw
signature-pad.drawingArea{label} drawing area
signature-pad.drawOrTypeDraw or type
signature-pad.signatureMethodSignature method
signature-pad.typeType
signature-pad.typeLabelType {label}
signature-pad.typeYourFullNameType your full name
signature-pad.undoLastStrokeUndo last stroke
slider-range.maximum{label} maximum
slider-range.minimum{label} minimum
snippet-tabs.code{label} code
snippet-tabs.languageLanguage
sources-list.showAllShow all
sources-list.titleSources
sparkline.noData{label}: no data
sparkline.range{label}: from {from} to {to}
spinner.labelLoading
split-view.labelList
split-view.label2Detail
split-view.resizeListResize list
spotlight-search.placeholderSpotlight Search
spotlight-search.titleSpotlight Search
spring-drawer.closeLabelClose
spring-drawer.handleLabelResize drawer
status-badge-row.historyDays{name} history, {length} days
status-badge-row.titleSystem status
status-badge-row.todayToday
status-badge-row.uptime{percent}% uptime
stepper-form.backBack
stepper-form.completeLabelComplete
stepper-form.progressProgress
stepper-form.readyReady
stepper-form.stepCompleted{title}, step {n} of {total}, completed
stepper-form.stepLabel{title}, step {n} of {total}
stepper-form.stepOfStep {n} of {total}
suggestion-chips.labelSuggested prompts
suggestion-chips.refreshLabelShow other suggestions
table-of-contents.titleOn this page
tag-input.labelTags
tag-input.placeholderAdd a tag…
tag-input.removeRemove {tag}
team-switcher.addLabelAdd team
team-switcher.teamsTeams
terminal.copiedCopied
terminal.copyCommandCopy command
terminal.terminalTerminal
thinking-indicator.labelThinking
thinking-indicator.statusLabelAssistant is thinking
time-picker.labelTime
toast-stack.dismissDismiss {title}
toast-stack.labelNotifications
token-meter.fullContext is full
token-meter.left{left} left
token-meter.nearingLimitNearing the limit, {left} left
token-meter.pill{title}: {percent}% used. {state}.
token-meter.summary{used} of {limit} tokens used, {percent}%. {state}.
token-meter.titleContext window
toolbar.ariaLabelSearch
toolbar.clearSearchClear search
toolbar.searchSearch
user-menu.signOutSign out
video-dialog.closeVideoClose video
video-dialog.playVideoPlay video: {title}
video-dialog.videoPlayerPressEscapeToVideo player. Press Escape to close.
voice-input.discardRecordingDiscard recording
voice-input.labelStart voice input
voice-input.processingLabelTranscribing…
voice-input.recordingTimeRecording time
voice-input.stopAndUseRecordingStop and use recording
webhook-card.eventsEvents
webhook-card.hideSigningSecretHide signing secret
webhook-card.moreEvents+{count} more
webhook-card.noDeliveriesYetEventsAppearNo deliveries yet. Events appear here as soon as they are sent.
webhook-card.recentDeliveriesRecent deliveries
webhook-card.redeliverRedeliver
webhook-card.requestBodyRequest body
webhook-card.revealSigningSecretReveal signing secret
webhook-card.sendEventsToThisEndpointSend events to this endpoint
webhook-card.sendTestEventSend test event
webhook-card.signingSecretSigning secret
webhook-card.successRate{percent}% of {count} deliveries succeeded
webhook-card.webhookWebhook {url}
webhook-card.yourResponseYour response
widgets.noEventsTodayNo events today
window-manager.labelDesktop
window-manager.restoreRestore {title}
window-manager.trayLabelMinimized windows
window-manager.windowAltAndArrowKeys{title} window. Alt and arrow keys move it; Alt, Shift and arrow keys resize it.
workspace-card.actions{name} actions
workspace-card.currentCurrent
workspace-card.loadingWorkspaceLoading workspace
workspace-card.storageUsedStorage used