diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx
index 861a559a..26132494 100644
--- a/src/components/common/messaging/MessageBase.tsx
+++ b/src/components/common/messaging/MessageBase.tsx
@@ -218,7 +218,7 @@ export const MessageDetail = observer(
@@ -236,7 +236,7 @@ export const MessageDetail = observer(
diff --git a/src/components/ui/fluent/CategoryButton.tsx b/src/components/ui/fluent/CategoryButton.tsx
new file mode 100644
index 00000000..39298ce8
--- /dev/null
+++ b/src/components/ui/fluent/CategoryButton.tsx
@@ -0,0 +1,26 @@
+import styled from "styled-components";
+
+import { Children } from "../../../types/Preact";
+
+const CategoryBase = styled.div`
+ height: 54px;
+ padding: 8px 12px;
+ border-radius: 6px;
+ margin-bottom: 10px;
+
+ background: var(--secondary-header);
+
+ gap: 12px;
+ display: flex;
+ align-items: center;
+ flex-direction: row;
+`;
+
+interface Props {
+ icon?: Children;
+ children?: Children;
+}
+
+export default function CategoryButton({ icon, children }: Props) {
+ return {icon};
+}
diff --git a/src/context/Locale.tsx b/src/context/Locale.tsx
index 7572bd78..3fc7e2e8 100644
--- a/src/context/Locale.tsx
+++ b/src/context/Locale.tsx
@@ -149,35 +149,60 @@ interface Props {
locale: Language;
}
+export interface Dictionary {
+ dayjs?: {
+ defaults?: {
+ twelvehour?: "yes" | "no";
+ separator?: string;
+ date?: "traditional" | "simplified" | "ISO8601";
+ };
+ timeFormat?: string;
+ };
+ [key: string]:
+ | Record>
+ | string
+ | undefined;
+}
+
function Locale({ children, locale }: Props) {
- // TODO: create and use LanguageDefinition type here
- const [defns, setDefinition] =
- useState>(definition);
- const lang = Languages[locale];
+ const [defns, setDefinition] = useState(definition as any);
+
+ // Load relevant language information, fallback to English if invalid.
+ const lang = Languages[locale] ?? Languages.en;
- // TODO: clean this up and use the built in Intl API
function transformLanguage(source: { [key: string]: any }) {
+ // Fallback untranslated strings to English (UK)
const obj = defaultsDeep(source, definition);
- const dayjs = obj.dayjs;
- const defaults = dayjs.defaults;
+ // Take relevant objects out, dayjs and defaults
+ // should exist given we just took defaults above.
+ const { dayjs } = obj;
+ const { defaults } = dayjs;
+
+ // Determine whether we are using 12-hour clock.
const twelvehour = defaults?.twelvehour
? defaults.twelvehour === "yes"
: false;
+ // Determine what date separator we are using.
const separator: string = defaults?.date_separator ?? "/";
+
+ // Determine what date format we are using.
const date: "traditional" | "simplified" | "ISO8601" =
defaults?.date_format ?? "traditional";
+ // Available date formats.
const DATE_FORMATS = {
traditional: `DD${separator}MM${separator}YYYY`,
simplified: `MM${separator}DD${separator}YYYY`,
ISO8601: "YYYY-MM-DD",
};
- dayjs["sameElse"] = DATE_FORMATS[date];
+ // Replace data in dayjs object, make sure to provide fallbacks.
+ dayjs["sameElse"] = DATE_FORMATS[date] ?? DATE_FORMATS.traditional;
dayjs["timeFormat"] = twelvehour ? "hh:mm A" : "HH:mm";
+ // Replace {{time}} format string in dayjs strings with the time format.
Object.keys(dayjs)
.filter((k) => typeof dayjs[k] === "string")
.forEach(
@@ -191,8 +216,10 @@ function Locale({ children, locale }: Props) {
return obj;
}
- useEffect(() => {
+ function loadLanguage(locale: string) {
if (locale === "en") {
+ // If English, make sure to restore everything to defaults.
+ // Use what we already have.
const defn = transformLanguage(definition);
setDefinition(defn);
dayjs.locale("en");
@@ -202,24 +229,33 @@ function Locale({ children, locale }: Props) {
import(`../../external/lang/${lang.i18n}.json`).then(
async (lang_file) => {
+ // Transform the definitions data.
const defn = transformLanguage(lang_file.default);
+
+ // Determine and load dayjs locales.
const target = lang.dayjs ?? lang.i18n;
const dayjs_locale = await import(
`../../node_modules/dayjs/esm/locale/${target}.js`
);
+ // Load dayjs locales.
dayjs.locale(target, dayjs_locale.default);
if (defn.dayjs) {
+ // Override dayjs calendar locales with our own.
dayjs.updateLocale(target, { calendar: defn.dayjs });
}
+ // Apply definition to app.
setDefinition(defn);
},
);
- }, [locale, lang]);
+ }
+
+ useEffect(() => loadLanguage(locale), [locale, lang]);
useEffect(() => {
+ // Apply RTL language format.
document.body.style.direction = lang.rtl ? "rtl" : "";
}, [lang.rtl]);
diff --git a/src/lib/i18n.tsx b/src/lib/i18n.tsx
index 769314ad..0507e78a 100644
--- a/src/lib/i18n.tsx
+++ b/src/lib/i18n.tsx
@@ -1,6 +1,8 @@
import { IntlContext, translate } from "preact-i18n";
import { useContext } from "preact/hooks";
+import { Dictionary } from "../context/Locale";
+
import { Children } from "../types/Preact";
interface Fields {
@@ -12,18 +14,6 @@ interface Props {
fields: Fields;
}
-export interface Dictionary {
- dayjs: {
- defaults: {
- twelvehour: "yes" | "no";
- separator: string;
- date: "traditional" | "simplified" | "ISO8601";
- };
- timeFormat: string;
- };
- [key: string]: Object | string;
-}
-
export interface IntlType {
intl: {
dictionary: Dictionary;