Skip to content

Commit

Permalink
feat: show the preferred locale first in the list of all locales
Browse files Browse the repository at this point in the history
  • Loading branch information
aradzie committed Mar 12, 2024
1 parent b963f56 commit 91e229e
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 139 deletions.
20 changes: 19 additions & 1 deletion packages/keybr-intl/lib/locale.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from "ava";
import { allLocales } from "./locale.ts";
import { allLocales, selectLocale } from "./locale.ts";

test("all locales", (t) => {
for (const id of allLocales) {
Expand All @@ -8,3 +8,21 @@ test("all locales", (t) => {
});
}
});

test("select preferred locale", (t) => {
const filter =
(...found: string[]) =>
(...locales: string[]): string | null =>
locales.find((locale) => found.includes(locale)) ?? null;
t.is(selectLocale(filter()), "en");
t.is(selectLocale(filter("xx")), "en");
t.is(selectLocale(filter("en")), "en");
t.is(selectLocale(filter("en-US")), "en");
t.is(selectLocale(filter("en-CA")), "en");
t.is(selectLocale(filter("pt")), "en");
t.is(selectLocale(filter("pt-BR")), "pt-br");
t.is(selectLocale(filter("pt-PT")), "en");
t.is(selectLocale(filter("zh")), "zh-hans");
t.is(selectLocale(filter("zh-CN")), "zh-hans");
t.is(selectLocale(filter("zh-TW")), "en");
});
45 changes: 40 additions & 5 deletions packages/keybr-intl/lib/locale.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { createContext, useContext } from "react";

export type LocaleId =
| "cs"
| "da"
Expand All @@ -20,12 +22,14 @@ export type LocaleId =
| "uk"
| "zh-hans";

export const defaultLocale: LocaleId = "en";

export const allLocales: readonly LocaleId[] = [
defaultLocale,
"cs",
"da",
"de",
"el",
"en",
"es",
"et",
"fr",
Expand All @@ -43,9 +47,40 @@ export const allLocales: readonly LocaleId[] = [
"zh-hans",
];

export const defaultLocale: LocaleId = "en";
export function getDir(locale: LocaleId): "rtl" | "ltr" {
return locale === "he" ? "rtl" : "ltr";
}

export const PreferredLocaleContext = createContext<LocaleId>(defaultLocale);

export function usePreferredLocale(): LocaleId {
return useContext(PreferredLocaleContext);
}

const map = (() => {
const map = new Map<string, LocaleId>();

// Append the default region to a language.
// This will add "en" as "en-US", "pt-BR" as "pt-BR",
// "zh-Hans" as "zh-CN", "zh-Hant" as "zh-TW", etc.
for (const id of allLocales) {
const locale = new Intl.Locale(id).maximize();
map.set(locale.language + "-" + locale.region, id);
}

// Append languages only.
for (const id of allLocales) {
const locale = new Intl.Locale(id);
if (locale.region == null) {
map.set(locale.language, id);
}
}

export const isRtl = (locale: LocaleId): boolean => locale === "he";
return map;
})();

export const getDir = (locale: LocaleId): string =>
isRtl(locale) ? "rtl" : "ltr";
export function selectLocale(
filter: (...locales: readonly string[]) => string | null,
): LocaleId {
return map.get(filter(...map.keys()) ?? "") ?? defaultLocale;
}
10 changes: 6 additions & 4 deletions packages/keybr-pages-server/lib/NavMenu.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FakeIntlProvider } from "@keybr/intl";
import { FakeIntlProvider, PreferredLocaleContext } from "@keybr/intl";
import { PageDataContext, Sitemap } from "@keybr/pages-shared";
import test from "ava";
import TestRenderer from "react-test-renderer";
Expand All @@ -22,9 +22,11 @@ test("render", (t) => {
extra: {},
}}
>
<FakeIntlProvider>
<NavMenu currentLink={Sitemap.practice.bind(null)} />
</FakeIntlProvider>
<PreferredLocaleContext.Provider value="pl">
<FakeIntlProvider>
<NavMenu currentLink={Sitemap.practice.bind(null)} />
</FakeIntlProvider>
</PreferredLocaleContext.Provider>
</PageDataContext.Provider>,
);

Expand Down
80 changes: 39 additions & 41 deletions packages/keybr-pages-server/lib/NavMenu.test.tsx.md
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,44 @@ Generated by [AVA](https://avajs.dev).
},
type: 'a',
},
{
children: [
'Polski',
],
props: {
className: 'link localeLink',
download: undefined,
href: '/pl/index',
id: undefined,
onClick: undefined,
onMouseDown: undefined,
onMouseEnter: undefined,
onMouseLeave: undefined,
onMouseUp: undefined,
target: undefined,
title: undefined,
},
type: 'a',
},
{
children: [
'English',
],
props: {
className: 'link localeLink',
download: undefined,
href: '/',
id: undefined,
onClick: undefined,
onMouseDown: undefined,
onMouseEnter: undefined,
onMouseLeave: undefined,
onMouseUp: undefined,
target: undefined,
title: undefined,
},
type: 'a',
},
{
children: [
{
Expand Down Expand Up @@ -827,26 +865,6 @@ Generated by [AVA](https://avajs.dev).
type: 'a',
},
' ',
{
children: [
'en',
],
props: {
className: 'link localeLink',
download: undefined,
href: '/',
id: undefined,
onClick: undefined,
onMouseDown: undefined,
onMouseEnter: undefined,
onMouseLeave: undefined,
onMouseUp: undefined,
target: undefined,
title: 'English',
},
type: 'a',
},
' ',
{
children: [
'es',
Expand Down Expand Up @@ -1007,26 +1025,6 @@ Generated by [AVA](https://avajs.dev).
type: 'a',
},
' ',
{
children: [
'pl',
],
props: {
className: 'link localeLink',
download: undefined,
href: '/pl/index',
id: undefined,
onClick: undefined,
onMouseDown: undefined,
onMouseEnter: undefined,
onMouseLeave: undefined,
onMouseUp: undefined,
target: undefined,
title: 'Polski',
},
type: 'a',
},
' ',
{
children: [
'pt-br',
Expand Down Expand Up @@ -1148,7 +1146,7 @@ Generated by [AVA](https://avajs.dev).
},
],
props: {
className: 'localeSwitcher',
className: 'localeList',
},
type: 'span',
},
Expand Down
Binary file modified packages/keybr-pages-server/lib/NavMenu.test.tsx.snap
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/keybr-pages-server/lib/SecondaryMenu.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
text-decoration: underline dotted var(--text-color);
}

.localeSwitcher {
.localeList {
margin-inline: 2rem;
margin-block: 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const secondaryMenu: string;
export const localeSwitcher: string;
export const localeList: string;
export const localeLink: string;
55 changes: 43 additions & 12 deletions packages/keybr-pages-server/lib/SecondaryMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { allLocales, useIntlDisplayNames } from "@keybr/intl";
import {
allLocales,
defaultLocale,
useIntlDisplayNames,
usePreferredLocale,
} from "@keybr/intl";
import {
type BoundPageLink,
isPremiumUser,
Expand Down Expand Up @@ -128,21 +133,47 @@ function LocaleSwitcher({
readonly currentLink: BoundPageLink;
}): ReactNode {
const { formatLocalLanguageName } = useIntlDisplayNames();
const children = [];
for (const locale of allLocales) {
if (children.length > 0) {
children.push(" ");
}
children.push(
const preferredLocale = usePreferredLocale();
const primary = [];
primary.push(
<Link
className={styles.localeLink}
href={currentLink.formatPath(preferredLocale)}
>
{formatLocalLanguageName(preferredLocale)}
</Link>,
);
if (preferredLocale !== defaultLocale) {
primary.push(
<Link
key={locale}
className={styles.localeLink}
href={currentLink.formatPath(locale)}
title={formatLocalLanguageName(locale)}
href={currentLink.formatPath(defaultLocale)}
>
{locale}
{formatLocalLanguageName(defaultLocale)}
</Link>,
);
}
return <span className={styles.localeSwitcher}>{children}</span>;
const secondary = [];
for (const locale of allLocales) {
if (locale !== preferredLocale && locale !== defaultLocale) {
if (secondary.length > 0) {
secondary.push(" ");
}
secondary.push(
<Link
className={styles.localeLink}
href={currentLink.formatPath(locale)}
title={formatLocalLanguageName(locale)}
>
{locale}
</Link>,
);
}
}
return (
<>
{...primary}
<span className={styles.localeList}>{...secondary}</span>
</>
);
}
Loading

0 comments on commit 91e229e

Please sign in to comment.