Quick Example

LocaleButton Usage

ตัวอย่าง import และการใช้งานแบบสั้นสำหรับหน้า `locale-button`

Code

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 import { setLocale, toLocale } from '$lib/paraglide/runtime'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]

 let locale = 'en'
</script>

<LocaleButton
 {locales}
 {locale}
 onLocaleChange={(nextLocale) => {
  locale = nextLocale
  const target = toLocale(nextLocale)
  if (target) {
   return setLocale(target, { reload: false })
  }
 }}
/>
            

LocaleButton

A language switcher button designed to work nicely with Paraglide. Use onLocaleChange for setLocale() flows while keeping the current path unchanged.

Basic Usage

Current locale: en

Choose Your Strategy

LocaleButton is only the UI layer. Your app decides how locale changes are applied.

Callback Strategy

Recommended

Use onLocaleChange when your app controls locale changes in code. This works well with Paraglide cookie-based setups and custom i18n stores.

  • Keeps the current pathname unchanged
  • Works with setLocale(..., { reload: false })
  • Best default for consumer apps

Href Strategy

Optional

Use getLocaleHref when your app intentionally exposes locale-specific URLs such as /th/docs or /en/docs.

  • Generates per-locale links
  • Useful for URL-prefix routing
  • Navigation happens through hrefs instead of imperative state

Custom I18n

Flexible

You can use LocaleButton without Paraglide at all. Pass your own locale state, persistence, and translation runtime.

  • No hard dependency on Paraglide
  • Works with stores, cookies, or API-backed preferences
  • Good for non-SvelteKit or mixed stacks

Paraglide with setLocale

Use the selection callback when your app already manages locale changes in code.

Paraglide setLocale()

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 import { setLocale, toLocale } from '$lib/paraglide/runtime'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]
 
 let locale = 'en'
</script>

<LocaleButton
 {locale}
 {locales}
 onLocaleChange={(nextLocale) => {
  locale = nextLocale
  const target = toLocale(nextLocale)
  if (target) {
   return setLocale(target)
  }
 }}
/>
            

Use In Consumer Apps

LocaleButton is exported from the sv5ui-plus package and can be used in any app that installs this library.

The component does not depend on Paraglide internally. Your app provides locale, locales, and the locale-change logic through onLocaleChange or getLocaleHref.

Consumer app example

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 import { setLocale, toLocale } from '$lib/paraglide/runtime'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]
 
 let locale = 'en'
</script>

<LocaleButton
 {locales}
 {locale}
 onLocaleChange={(nextLocale) => {
  locale = nextLocale
  const target = toLocale(nextLocale)
  if (target) {
   return setLocale(target, { reload: false })
  }
 }}
/>
            

Keep The Same Path

With cookie-based Paraglide strategy, you can switch locale without adding /th or other locale prefixes to the URL.

Paraglide without locale prefix

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 import { setLocale, toLocale } from '$lib/paraglide/runtime'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]
 
 let locale = 'en'
</script>

<LocaleButton
 {locale}
 {locales}
 onLocaleChange={(nextLocale) => {
  locale = nextLocale
  const target = toLocale(nextLocale)
  if (target) {
   return setLocale(target, { reload: false })
  }
 }}
/>
            

Use Locale Prefix URLs

If your product intentionally uses locale-prefixed routes such as /th/docs, provide getLocaleHref. This keeps navigation declarative and lets the button render locale-specific links.

Href strategy with localizeHref()

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 import { localizeHref } from '$lib/paraglide/runtime'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]
 
 let locale = 'en'
 const pathname = '/docs/components/locale-button'
</script>

<LocaleButton
 {locales}
 {locale}
 getLocaleHref={(nextLocale) => localizeHref(pathname, { locale: nextLocale })}
/>
            

Use Without Paraglide

The component works with any locale source of truth. You can connect it to a Svelte store, cookies, localStorage, an API-backed user preference, or another i18n runtime.

Custom i18n integration

                <script lang="ts">
 import { LocaleButton, type LocaleButtonLocale } from 'sv5ui-plus'
 
 const locales: LocaleButtonLocale[] = [
   { code: 'en', label: 'English', shortLabel: 'EN' },
   { code: 'th', label: 'Thai', shortLabel: 'TH' }
 ]
 
 let locale = 'en'
 
 function applyLocale(nextLocale: string) {
   locale = nextLocale
   localStorage.setItem('preferred-locale', nextLocale)
 }
</script>

<LocaleButton
 {locales}
 {locale}
 onLocaleChange={(nextLocale) => {
  applyLocale(nextLocale)
 }}
/>
            

Locale Item Shape

Each locale entry is just data. Start with code and label, then add optional fields only when your app needs them.

LocaleButtonLocale[]

                import type { LocaleButtonLocale } from 'sv5ui-plus'

const locales: LocaleButtonLocale[] = [
  {
    code: 'en',
    label: 'English',
    shortLabel: 'EN',
    description: 'Default content language'
  },
  {
    code: 'th',
    label: 'Thai',
    shortLabel: 'TH',
    description: 'Thai translation',
    href: '/th/docs',
    hreflang: 'th'
  }
]
            
FieldRequiredPurpose
codeYesThe locale identifier used by your i18n layer, such as en or th.
labelYesThe full label rendered in the dropdown menu.
shortLabelNoCompact text for the trigger or badge, such as EN or TH.
descriptionNoSecondary helper text shown inside the menu.
hrefNoA precomputed locale-specific link if your app uses href navigation.
hreflangNoOptional hreflang value forwarded to anchor items.
disabledNoDisables a specific locale item.

Integration Checklist

  • Use onLocaleChange when you do not want locale prefixes in the URL.
  • Use getLocaleHref only when your routing strategy intentionally includes locale-specific paths.
  • Pass locale from your own source of truth so the trigger always reflects the current language.
  • Provide shortLabel values when you want compact trigger text such as EN, TH, or JA.
  • Use the children snippet when your product needs a fully custom trigger design.

Variants

Sizes

Control trigger button and dropdown menu item scaling from xs to xl. Font sizes, item padding, badge indicators, and icons scale proportionally.

Custom Trigger

Use the children snippet to fully control the trigger content while keeping the dropdown behavior.

Custom Menu Items

Use the item snippet to completely redesign how each language row looks inside the dropdown.

Custom Menu Layout

If you need to break out of the standard vertical list, use the menu snippet to build an entirely custom dropdown grid or layout.

Flag Icons Design

Here is a highly requested design: a circular flag trigger that reveals a dropdown of languages with flags. This uses both the children and item snippets.

Fit Content

Use the fit prop to shrink the dropdown menu width to fit its content (`w-fit min-w-0`) instead of using the default minimum width.

Positioning & Alignment

Control the dropdown popover position using side (`bottom`, `top`, `left`, `right`) and align (`start`, `center`, `end`).