mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -05:00
Start work on fluent categories.
Fix Locale loading when syncing invalid lang.
This commit is contained in:
parent
c93f0245f1
commit
8cc92e0c42
4 changed files with 76 additions and 24 deletions
|
@ -218,7 +218,7 @@ export const MessageDetail = observer(
|
||||||
<time className="copyTime">
|
<time className="copyTime">
|
||||||
<i className="copyBracket">[</i>
|
<i className="copyBracket">[</i>
|
||||||
{dayjs(decodeTime(message._id)).format(
|
{dayjs(decodeTime(message._id)).format(
|
||||||
dict.dayjs.timeFormat,
|
dict.dayjs?.timeFormat,
|
||||||
)}
|
)}
|
||||||
<i className="copyBracket">]</i>
|
<i className="copyBracket">]</i>
|
||||||
</time>
|
</time>
|
||||||
|
@ -236,7 +236,7 @@ export const MessageDetail = observer(
|
||||||
<time>
|
<time>
|
||||||
<i className="copyBracket">[</i>
|
<i className="copyBracket">[</i>
|
||||||
{dayjs(decodeTime(message._id)).format(
|
{dayjs(decodeTime(message._id)).format(
|
||||||
dict.dayjs.timeFormat,
|
dict.dayjs?.timeFormat,
|
||||||
)}
|
)}
|
||||||
<i className="copyBracket">]</i>
|
<i className="copyBracket">]</i>
|
||||||
</time>
|
</time>
|
||||||
|
|
26
src/components/ui/fluent/CategoryButton.tsx
Normal file
26
src/components/ui/fluent/CategoryButton.tsx
Normal file
|
@ -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 <CategoryBase>{icon}</CategoryBase>;
|
||||||
|
}
|
|
@ -149,35 +149,60 @@ interface Props {
|
||||||
locale: Language;
|
locale: Language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Dictionary {
|
||||||
|
dayjs?: {
|
||||||
|
defaults?: {
|
||||||
|
twelvehour?: "yes" | "no";
|
||||||
|
separator?: string;
|
||||||
|
date?: "traditional" | "simplified" | "ISO8601";
|
||||||
|
};
|
||||||
|
timeFormat?: string;
|
||||||
|
};
|
||||||
|
[key: string]:
|
||||||
|
| Record<string, Omit<Dictionary, "dayjs">>
|
||||||
|
| string
|
||||||
|
| undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function Locale({ children, locale }: Props) {
|
function Locale({ children, locale }: Props) {
|
||||||
// TODO: create and use LanguageDefinition type here
|
const [defns, setDefinition] = useState<Dictionary>(definition as any);
|
||||||
const [defns, setDefinition] =
|
|
||||||
useState<Record<string, unknown>>(definition);
|
// Load relevant language information, fallback to English if invalid.
|
||||||
const lang = Languages[locale];
|
const lang = Languages[locale] ?? Languages.en;
|
||||||
|
|
||||||
// TODO: clean this up and use the built in Intl API
|
|
||||||
function transformLanguage(source: { [key: string]: any }) {
|
function transformLanguage(source: { [key: string]: any }) {
|
||||||
|
// Fallback untranslated strings to English (UK)
|
||||||
const obj = defaultsDeep(source, definition);
|
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
|
const twelvehour = defaults?.twelvehour
|
||||||
? defaults.twelvehour === "yes"
|
? defaults.twelvehour === "yes"
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
// Determine what date separator we are using.
|
||||||
const separator: string = defaults?.date_separator ?? "/";
|
const separator: string = defaults?.date_separator ?? "/";
|
||||||
|
|
||||||
|
// Determine what date format we are using.
|
||||||
const date: "traditional" | "simplified" | "ISO8601" =
|
const date: "traditional" | "simplified" | "ISO8601" =
|
||||||
defaults?.date_format ?? "traditional";
|
defaults?.date_format ?? "traditional";
|
||||||
|
|
||||||
|
// Available date formats.
|
||||||
const DATE_FORMATS = {
|
const DATE_FORMATS = {
|
||||||
traditional: `DD${separator}MM${separator}YYYY`,
|
traditional: `DD${separator}MM${separator}YYYY`,
|
||||||
simplified: `MM${separator}DD${separator}YYYY`,
|
simplified: `MM${separator}DD${separator}YYYY`,
|
||||||
ISO8601: "YYYY-MM-DD",
|
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";
|
dayjs["timeFormat"] = twelvehour ? "hh:mm A" : "HH:mm";
|
||||||
|
|
||||||
|
// Replace {{time}} format string in dayjs strings with the time format.
|
||||||
Object.keys(dayjs)
|
Object.keys(dayjs)
|
||||||
.filter((k) => typeof dayjs[k] === "string")
|
.filter((k) => typeof dayjs[k] === "string")
|
||||||
.forEach(
|
.forEach(
|
||||||
|
@ -191,8 +216,10 @@ function Locale({ children, locale }: Props) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
function loadLanguage(locale: string) {
|
||||||
if (locale === "en") {
|
if (locale === "en") {
|
||||||
|
// If English, make sure to restore everything to defaults.
|
||||||
|
// Use what we already have.
|
||||||
const defn = transformLanguage(definition);
|
const defn = transformLanguage(definition);
|
||||||
setDefinition(defn);
|
setDefinition(defn);
|
||||||
dayjs.locale("en");
|
dayjs.locale("en");
|
||||||
|
@ -202,24 +229,33 @@ function Locale({ children, locale }: Props) {
|
||||||
|
|
||||||
import(`../../external/lang/${lang.i18n}.json`).then(
|
import(`../../external/lang/${lang.i18n}.json`).then(
|
||||||
async (lang_file) => {
|
async (lang_file) => {
|
||||||
|
// Transform the definitions data.
|
||||||
const defn = transformLanguage(lang_file.default);
|
const defn = transformLanguage(lang_file.default);
|
||||||
|
|
||||||
|
// Determine and load dayjs locales.
|
||||||
const target = lang.dayjs ?? lang.i18n;
|
const target = lang.dayjs ?? lang.i18n;
|
||||||
const dayjs_locale = await import(
|
const dayjs_locale = await import(
|
||||||
`../../node_modules/dayjs/esm/locale/${target}.js`
|
`../../node_modules/dayjs/esm/locale/${target}.js`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Load dayjs locales.
|
||||||
dayjs.locale(target, dayjs_locale.default);
|
dayjs.locale(target, dayjs_locale.default);
|
||||||
|
|
||||||
if (defn.dayjs) {
|
if (defn.dayjs) {
|
||||||
|
// Override dayjs calendar locales with our own.
|
||||||
dayjs.updateLocale(target, { calendar: defn.dayjs });
|
dayjs.updateLocale(target, { calendar: defn.dayjs });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply definition to app.
|
||||||
setDefinition(defn);
|
setDefinition(defn);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}, [locale, lang]);
|
}
|
||||||
|
|
||||||
|
useEffect(() => loadLanguage(locale), [locale, lang]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Apply RTL language format.
|
||||||
document.body.style.direction = lang.rtl ? "rtl" : "";
|
document.body.style.direction = lang.rtl ? "rtl" : "";
|
||||||
}, [lang.rtl]);
|
}, [lang.rtl]);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { IntlContext, translate } from "preact-i18n";
|
import { IntlContext, translate } from "preact-i18n";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
|
import { Dictionary } from "../context/Locale";
|
||||||
|
|
||||||
import { Children } from "../types/Preact";
|
import { Children } from "../types/Preact";
|
||||||
|
|
||||||
interface Fields {
|
interface Fields {
|
||||||
|
@ -12,18 +14,6 @@ interface Props {
|
||||||
fields: Fields;
|
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 {
|
export interface IntlType {
|
||||||
intl: {
|
intl: {
|
||||||
dictionary: Dictionary;
|
dictionary: Dictionary;
|
||||||
|
|
Loading…
Reference in a new issue