Weekdays that fit the weather columns, the top bar's own abbreviation, tile texts that fit, and a check that measures them

- The CYD's weather columns hold two letters beside the icon: every language has its own two-letter days (the CLDR's
  short width, Polish nd pn wt); French mar became nar there. check fails on a longer one.
- The top bar takes the language's abbreviation (sam. 19 sept., Sa., 19. Sept.), English keeps Sa 19 Sep.
- The editor's clock and date follow the screens: 7:05 PM in the top bar, 7:05 on the clock card.
- A long weather word ends in an ellipsis before the days.
- Tile lines that were cut on a screen are shorter (Zum Öffnen, Ouvrir, Otwórz, Sin imagen, ...); check measures
  them with the screens' font against the tile width of both boards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-19 17:13:59 +02:00
parent 365ed158b9
commit f02f429188
26 changed files with 145 additions and 81 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ import type { HeaderItem } from "../types";
const query = ref("");
const taken = computed(() => new Set(topbarItems().map(itemKey)));
const samples = computed(() => ({
clock: clockText(clock24.value, new Date(state.now)),
clock: clockText(clock24.value, new Date(state.now), screenLanguage.value),
analog: t("editor.topbar.analog_sample"),
date: dateText(new Date(state.now), screenLanguage.value),
} as Record<string, string>));
+1 -1
View File
@@ -51,7 +51,7 @@ const liveNote = computed(() => {
return !view.shown ? t("editor.topbar.live.hidden") : overflow.value.has(props.index) ? t("editor.topbar.live.overflow") : t("editor.topbar.live.looks");
});
const samples = computed(() => ({
clock: clockText(clock24.value, new Date(state.now)),
clock: clockText(clock24.value, new Date(state.now), screenLanguage.value),
analog: t("editor.topbar.analog_sample"),
date: dateText(new Date(state.now), screenLanguage.value),
} as Record<string, string>));
+10 -6
View File
@@ -12,14 +12,18 @@ export const BUILTIN_ICONS: Record<string, string> = { clock: "clock-outline", a
export const itemKey = (item: HeaderItem) => JSON.stringify(item);
export const glyph = (cp: string) => String.fromCodePoint(parseInt(cp, 16));
export function clockText(clock24: boolean, now = new Date()) {
let hours = now.getHours();
// The screen formats with %I:%M when the 24-hour clock is off.
if (!clock24) hours = hours % 12 || 12;
return `${String(hours).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
// The time as the screens write it (screen_text::clock_text): "07:12" on 24 hours; on 12 "7:12 PM" in the top bar, with
// the language's day periods, and "7:12" in the clock card's big digits, which have no letters.
export function clockText(clock24: boolean, now = new Date(), locale?: string) {
const minutes = String(now.getMinutes()).padStart(2, "0");
if (clock24) return `${String(now.getHours()).padStart(2, "0")}:${minutes}`;
const time = `${now.getHours() % 12 || 12}:${minutes}`;
return locale ? `${time} ${t(`screen.time.${now.getHours() < 12 ? "am" : "pm"}`, {}, { locale })}` : time;
}
// "Sa 19 Sep", "za 19 sep", "sam. 19 sept.": the language's pattern with its abbreviation or its two letters.
export const dateText = (now = new Date(), locale = "en") => t("screen.date.top_bar", {
weekday: t(`screen.date.weekdays_min.${now.getDay()}`, {}, { locale }),
weekday: t(`screen.date.weekdays_short.${now.getDay()}`, {}, { locale }),
weekday_min: t(`screen.date.weekdays_min.${now.getDay()}`, {}, { locale }),
day: now.getDate(),
month: t(`screen.date.months_short.${now.getMonth()}`, {}, { locale }),
}, { locale });
+1 -1
View File
@@ -583,7 +583,7 @@ export function topbarLabel(item: HeaderItem) {
// What the item shows right now: { icon, text, color, shown }. Entities wait for the add-on's preview.
export function topbarView(item: HeaderItem): ItemView {
const now = new Date(state.now);
if (item.type === "clock") return { text: clockText(clock24.value, now), shown: true };
if (item.type === "clock") return { text: clockText(clock24.value, now, screenLanguage.value), shown: true };
if (item.type === "date") return { text: dateText(now, screenLanguage.value), shown: true };
if (item.type === "analog") return { analog: true, shown: true };
const p = state.topbarPreviews[itemKey(item)];