Skip to content

Internationalization (i18n) ​

BrutxUI includes a built-in lightweight multi-language system, defaulting to Chinese (zh-CN) with an official English (en) locale pack. No mandatory installation of vue-i18n is required.


Design Principles ​

  • Zero Mandatory Third-Party Dependencies: Built-in lightweight locale system based on Vue's provide/inject, which can also seamlessly integrate with vue-i18n;
  • Default Chinese: All components default to simplified Chinese (zh-CN);
  • Hierarchical Priority: Explicit Component Props > Local texts Prop > provideLocale Injection > Global Plugin Config > Default zh-CN;
  • Reactive Updates: Pass a Ref or ComputedRef to trigger instant live updates upon language changes.

Resolution Priority ​

Component texts resolve in descending order of precedence:

text
Component Explicit Props > Component texts Prop > provideLocale Injected Value > Global Plugin Config > Default Chinese (zh-CN)

Quick Start ​

1. Default Chinese (Zero Configuration) ​

Without any configuration, components render standard Chinese strings:

vue
<template>
    <CommandInput />
    <!-- Default placeholder displays "输入命令或搜索..." -->
</template>

2. Global English Configuration ​

Configure the locale in your application entry point:

ts
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { BrutxUIPlugin, en } from 'brutx-ui-vue'

const app = createApp(App)
app.use(BrutxUIPlugin, { locale: en })
app.mount('#app')

Reactive Dynamic Language Switching ​

provideLocale accepts MaybeRef<Locale>. Passing a computed or ref updates all descendant components seamlessly:

vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { provideLocale, zhCN, en, Button, CommandInput } from 'brutx-ui-vue'

const currentLang = ref<'zh' | 'en'>('zh')
const activeLocale = computed(() => (currentLang.value === 'en' ? en : zhCN))

// Inject reactive locale to subtree
provideLocale(activeLocale)

function toggleLanguage() {
    currentLang.value = currentLang.value === 'zh' ? 'en' : 'zh'
}
</script>

<template>
    <div class="flex flex-col gap-4 p-4">
        <div class="flex items-center gap-2">
            <Button variant="default" size="sm" @click="toggleLanguage">
                Switch to {{ currentLang === 'zh' ? 'English' : '中文' }}
            </Button>
        </div>
        <CommandInput />
    </div>
</template>

Subtree Overrides and Fallback Locales ​

Subtree Locale Override ​

Use provideLocale to isolate a subtree to a specific language without affecting outer modules:

vue
<script setup lang="ts">
import { provideLocale, en, CommandInput } from 'brutx-ui-vue'

// This component and all descendants render in English
provideLocale(en)
</script>

<template>
    <div class="border-3 border-brutal p-4">
        <CommandInput />
    </div>
</template>

Custom Fallback Locale ​

If a custom locale only translates a subset of keys, provide a fallback locale:

vue
<script setup lang="ts">
import { provideLocale, en } from 'brutx-ui-vue'

provideLocale({
    locale: en,
    fallbackLocale: {
        popconfirm: { confirm: 'Proceed', cancel: 'Dismiss' },
    },
})
</script>

Resolution chain: Active locale → Custom fallbackLocale → Built-in zhCN → Raw path string.


Deep Merging and Customization ​

Partial Override with mergeLocale ​

Deep merge with existing locale packs to customize specific messages:

ts
import { zhCN, mergeLocale } from 'brutx-ui-vue'

const customZh = mergeLocale(zhCN, {
    command: {
        placeholder: 'Type a command or search docs...',
    },
    dataTable: {
        emptyText: 'No matching records found',
    },
})

Coexisting with vue-i18n ​

When integrating with vue-i18n, keep BrutxUI synchronized via a computed property:

vue
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { provideLocale, zhCN, en } from 'brutx-ui-vue'

const { locale } = useI18n()

// Map vue-i18n locale to BrutxUI pack
const brutxLocale = computed(() => (locale.value === 'en' ? en : zhCN))
provideLocale(brutxLocale)
</script>

useLocale Composable ​

Read current locale settings or perform interpolated translation:

vue
<script setup lang="ts">
import { useLocale } from 'brutx-ui-vue'

const { locale, t } = useLocale()

// Standard key translation
const placeholder = t('command.placeholder')

// Translation with interpolation parameters
const countLabel = t('combobox.selectedCount', { count: 5 }) // "5 selected"
const pageInfo = t('pagination.page', { number: 3 })         // "Page 3"
</script>

Supported Component & Key Index (52+ Components) ​

Module / ComponentKey PrefixCore Keys & Interpolation Parameters
Commandcommand.*placeholder, emptyText, dialogTitle, dialogDescription, searchLabel
Comboboxcombobox.*placeholder, multiPlaceholder, searchPlaceholder, emptyText, selectedCount ({count}), create
Paginationpagination.*firstPage, previousPage, nextPage, lastPage, page ({number}), perPageOption ({size}), total ({total})
Carouselcarousel.*previousSlide, nextSlide, goToSlide ({index})
Spinnerspinner.*loading
Button / SubmitsubmitButton.*submitting
CopyToClipboardcopyToClipboard.*copy, copied, copyFailed
BeforeAfterbeforeAfter.*before, after, comparisonSlider
AuthCardauthCard.*welcomeBack, signInToContinue, google, github, orEmailLogin, email, password, signIn, register
DashboardShelldashboardShell.*sidebarNavigation, signOut, brand, openNavigation, closeNavigation
BrutalistHerobrutalistHero.*title, primaryCtaText, secondaryCtaText, neoBrutalismUI, defaultSubtitle
CardWindowHeadercardWindowHeader.*close, minimize, maximize
Toasttoast.*close, container
Messagemessage.*close
Dialogdialog.*close
MessageBoxmessageBox.*confirm, cancel
Sheetsheet.*close
Breadcrumbbreadcrumb.*label, more
TreeViewtreeView.*fileTree
TreeSelecttreeSelect.*placeholder, emptyText
Cascadercascader.*placeholder, emptyText
Transfertransfer.*availableTitle, selectedTitle, searchPlaceholder, emptyText, clearAll, selectAll, itemCount ({count})
Stepperstepper.*progressSteps, step ({index}, {title})
HeaderSectionheaderSection.*defaultLogoText, defaultCtaText, menuLabel
FooterSectionfooterSection.*defaultLogoText, defaultDescription, defaultCopyright
FeedbackFormfeedbackForm.*defaultTitle, defaultDescription, defaultSubmitText, successTitle, nameLabel, emailLabel, messageLabel
CookieConsentcookieConsent.*defaultTitle, defaultDescription, defaultAcceptText, defaultDeclineText
DataTabledataTable.*emptyText, searchPlaceholder, selectedCount ({count})
FormWizardformWizard.*previous, next, submit
ChatBubblechatBubble.*delivered, read
ScratchCardscratchCard.*ariaLabel
SketchyChartsketchyChart.*lineAriaLabel, barAriaLabel, pieAriaLabel
Card3Dcard3d.*ariaLabel
Avataravatar.*fallback
HardcoreInputhardcoreInput.*invalidInput
CodeBlockcodeBlock.*copy, copied, expand, collapse
Calendarcalendar.*previousMonth, nextMonth
DatePickerdatePicker.*placeholder, clear
ColorPickercolorPicker.*placeholder, clear
Kanbankanban.*dropCardsHere, addCard, cardGrabbed, cardReleased, cardMoved, cardMovedToColumn ({column})
Timelinetimeline.*label
Tabstabs.*more
PricingSectionpricingSection.*defaultTitle, mostPopular, perLifetime, planStarterName, planProName, planEnterpriseName
ColorModeSwitchercolorModeSwitcher.*light, dark, system, toggleTheme
Input / NumberInput / Textareainput.* / numberInput.* / textarea.*placeholder
VirtualScroll / InfiniteScrollvirtualScroll.* / infiniteScroll.*emptyText / loading
Switch / Checkboxswitch.* / checkbox.*checked, unchecked
TagsInputtagsInput.*placeholder, remove
Badge / Alertbadge.* / alert.*close
Popconfirmpopconfirm.*confirm, cancel
Uploadupload.*dragText, browseText, maxSizeError, limitError ({limit}), retry
Tourtour.*prev, next, finish, skip
Statisticstatistic.*empty, up, down
Countdowncountdown.*finished

Brute force builds.