Skip to content

Commit 3a751cb

Browse files
committed
Sort locales by label in language panel
1 parent 52479df commit 3a751cb

3 files changed

Lines changed: 76 additions & 17 deletions

File tree

src/lib/components/settings/panels/language-panel.svelte

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@
2020
onChange = undefined,
2121
/* eslint-enable prefer-const, no-unused-vars */
2222
} = $props();
23+
24+
/**
25+
* Locale list sorted by label.
26+
*/
27+
const locales = $derived(
28+
appLocales
29+
.map((code) => ({
30+
value: code,
31+
label: getLocaleLabel(code, { displayLocale: code }) ?? code,
32+
}))
33+
.sort((a, b) => a.label.localeCompare(b.label)),
34+
);
2335
</script>
2436
2537
<section>
@@ -33,13 +45,8 @@
3345
prefs.locale = event.detail.value;
3446
}}
3547
>
36-
{#each appLocales as locale (locale)}
37-
<Option
38-
label={getLocaleLabel(locale, { displayLocale: locale }) ?? locale}
39-
value={locale}
40-
selected={locale === appLocale.current}
41-
dir="auto"
42-
/>
48+
{#each locales as { value, label } (value)}
49+
<Option {value} {label} selected={value === appLocale.current} dir="auto" />
4350
{/each}
4451
</Select>
4552
{/key}

src/lib/services/contents/i18n/index.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ import { locale as appLocale, isRTL } from '@sveltia/i18n';
55
* @import { LocaleCode } from '$lib/types/public';
66
*/
77

8+
/**
9+
* Default options for `Intl.DisplayNames()`. Use `English (US)` instead of `American English` for a
10+
* better language listing.
11+
* @type {Intl.DisplayNamesOptions}
12+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames
13+
*/
14+
const LANG_FORMATTER_OPTIONS = {
15+
type: 'language',
16+
languageDisplay: 'standard',
17+
style: 'short',
18+
};
19+
820
/**
921
* Get the canonical locale of the given locale that can be used for various `Intl` methods.
1022
* @param {InternalLocaleCode} locale Locale.
@@ -46,12 +58,16 @@ const displayNamesCache = new Map();
4658
* @param {object} [options] Options.
4759
* @param {InternalLocaleCode} [options.displayLocale] Locale code to display the locale name. If
4860
* not given, use the current application locale. Default is `en`.
61+
* @param {Intl.DisplayNamesOptions} [options.formatterOptions] Options for `Intl.DisplayNames()`.
4962
* @returns {string | undefined} Locale label like `English`. If the locale is not valid, returns
5063
* `undefined`.
5164
*/
5265
export const getLocaleLabel = (
5366
locale,
54-
{ displayLocale = getCanonicalLocale(appLocale.current ?? 'en') } = {},
67+
{
68+
displayLocale = getCanonicalLocale(appLocale.current ?? 'en'),
69+
formatterOptions = LANG_FORMATTER_OPTIONS,
70+
} = {},
5571
) => {
5672
const canonicalLocale = getCanonicalLocale(locale);
5773

@@ -65,11 +81,11 @@ export const getLocaleLabel = (
6581
formatter = displayNamesCache.get(displayLocale);
6682

6783
if (!formatter) {
68-
formatter = new Intl.DisplayNames(displayLocale, { type: 'language' });
84+
formatter = new Intl.DisplayNames(displayLocale, formatterOptions);
6985
displayNamesCache.set(displayLocale, formatter);
7086
}
7187
} else {
72-
formatter = new Intl.DisplayNames(undefined, { type: 'language' });
88+
formatter = new Intl.DisplayNames(undefined, formatterOptions);
7389
}
7490

7591
try {

src/lib/services/contents/i18n/index.test.js

Lines changed: 43 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)