Skip to content

ConfigProvider

Provides global configuration for descendant components, primarily used for internationalization (i18n) locale switching.

NameCategoryDescriptionType
locale? BehaviorLanguage configuration object to override default component languageLanguage
extendsI18nMsg? BehaviorExtended i18n messages, merged with existing messagesTranslatePair
default? SlotDefault slot for wrapping components that need global configuration{ config: ConfigProviderProps }

Usage

Wrap your application (or a subtree) with <px-config-provider> and pass a locale object to switch the language of all components within. The demo below shows a Select (with "No data" placeholder), a Popconfirm (with translated Yes / No buttons), and a MessageBox — all responding to the same locale picker.

Note: PxMessageBox() is an imperative API that renders into a detached container, so it cannot inherit locale from ConfigProvider. You need to pass translated strings explicitly (e.g. confirmButtonText, cancelButtonText, title) from the locale object.

<template>
  <div class="demo-config-provider">
    <div style="margin-bottom: 16px">
      <label for="locale-picker" style="margin-right: 8px; font-weight: bold">
        Locale:
      </label>
      <select
        id="locale-picker"
        :value="localeKey"
        @change="localeKey = ($event.target as HTMLSelectElement).value"
        style="padding: 4px 8px; font-size: 14px"
      >
        <option v-for="opt in localeOptions" :key="opt.value" :value="opt.value">
          {{ opt.label }}
        </option>
      </select>
    </div>

    <px-config-provider :locale="currentLocale">
      <div style="display: flex; align-items: flex-start; gap: 24px; flex-wrap: wrap">
        <!-- Select: shows translated placeholder and "No data" -->
        <div>
          <p style="margin: 0 0 8px; font-weight: bold">Select</p>
          <px-select
            v-model="selectVal"
            :options="emptyOptions"
            filterable
            style="width: 200px"
          />
        </div>

        <!-- Popconfirm: shows translated Yes / No -->
        <div>
          <p style="margin: 0 0 8px; font-weight: bold">Popconfirm</p>
          <px-popconfirm title="Are you sure?">
            <px-button type="danger">Delete</px-button>
          </px-popconfirm>
        </div>

        <!-- MessageBox: explicit translated text -->
        <div>
          <p style="margin: 0 0 8px; font-weight: bold">MessageBox</p>
          <px-button type="primary" @click="openMessageBox">
            Open MessageBox
          </px-button>
        </div>
      </div>

      <!-- Translation Preview -->
      <table class="translation-table">
        <thead>
          <tr>
            <th class="translation-key">Key</th>
            <th>Translation</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="row in translationPreview" :key="row.key">
            <td class="translation-key">{{ row.key }}</td>
            <td>{{ row.value }}</td>
          </tr>
        </tbody>
      </table>
    </px-config-provider>
  </div>
</template>

<script setup lang="ts">
import { en, ja, ko, PxMessageBox, zhCn, zhTw } from 'sakana-element';
import { computed, ref } from 'vue';

const localeMap: Record<string, { label: string; locale: typeof en }> = {
  en: { label: 'English', locale: en },
  zhCn: { label: '简体中文', locale: zhCn },
  zhTw: { label: '繁體中文', locale: zhTw },
  ja: { label: '日本語', locale: ja },
  ko: { label: '한국어', locale: ko },
};

const localeOptions = Object.entries(localeMap).map(([value, { label }]) => ({
  value,
  label,
}));

const localeKey = ref('en');
const currentLocale = computed(() => localeMap[localeKey.value].locale);

const selectVal = ref('');
const emptyOptions = ref([]);

const translationPreview = computed(() => {
  const el = currentLocale.value.el;
  return [
    { key: 'select.placeholder', value: el.select.placeholder },
    { key: 'select.noData', value: el.select.noData },
    { key: 'popconfirm.confirmButtonText', value: el.popconfirm.confirmButtonText },
    { key: 'popconfirm.cancelButtonText', value: el.popconfirm.cancelButtonText },
    { key: 'messagebox.confirm', value: el.messagebox.confirm },
    { key: 'messagebox.cancel', value: el.messagebox.cancel },
  ];
});

async function openMessageBox() {
  const msgLocale = currentLocale.value.el.messagebox;
  try {
    await PxMessageBox({
      title: msgLocale.title,
      message: 'This demonstrates locale-aware button text.',
      showCancelButton: true,
      cancelButtonText: msgLocale.cancel,
      confirmButtonText: msgLocale.confirm,
    });
  } catch {
    // cancelled
  }
}
</script>

<style scoped>
.translation-table {
  margin-top: 16px;
  border-collapse: collapse;
  font-size: 14px;
  text-align: left;
}

.translation-table th {
  padding: 4px 12px 4px 0;
  border-bottom: 1px solid var(--px-border-color);
}

.translation-table td {
  padding: 4px 12px 4px 0;
}

.translation-key {
  color: var(--px-text-color-secondary);
  font-family: monospace;
}
</style>

Extending i18n Messages

Use the extendsI18nMsg prop to override or add translation keys without replacing the entire locale. The object is deep-merged into the built-in messages, so you only need to specify the keys you want to change.

The shape must match the internal message structure — keyed by locale name at the top level:

typescript
const customMessages = {
  en: {
    popconfirm: {
      confirmButtonText: 'Sure!',
      cancelButtonText: 'Nope',
    },
  },
}

The demo below shows two Popconfirms side by side: one with default button text, and one with overridden text via extendsI18nMsg.

<template>
  <div style="display: flex; align-items: flex-start; gap: 48px; flex-wrap: wrap">
    <!-- Default Popconfirm -->
    <div>
      <p style="margin: 0 0 8px; font-weight: bold">Default</p>
      <px-config-provider>
        <px-popconfirm title="Are you sure?">
          <px-button>Delete</px-button>
        </px-popconfirm>
      </px-config-provider>
    </div>

    <!-- Popconfirm with extendsI18nMsg -->
    <div>
      <p style="margin: 0 0 8px; font-weight: bold">With extendsI18nMsg</p>
      <px-config-provider :extendsI18nMsg="customMessages">
        <px-popconfirm title="Are you sure?">
          <px-button type="primary">Delete</px-button>
        </px-popconfirm>
      </px-config-provider>
    </div>
  </div>
</template>

<script setup lang="ts">
const customMessages = {
  en: {
    popconfirm: {
      confirmButtonText: 'Sure!',
      cancelButtonText: 'Nope',
    },
  },
};
</script>

Available Locales

Sakana Element ships with the following built-in locales:

LocaleImport NameLanguage
EnglishenEnglish (default)
简体中文zhCnSimplified Chinese
繁體中文zhTwTraditional Chinese
日本語jaJapanese
한국어koKorean
js
import { en, zhCn, zhTw, ja, ko } from 'sakana-element'