Fix Schedule UI regressions and complete non-RU/EN locale translations

- Duration now sums segments + transfers (last arrival − first departure)
  for multi-leg/connecting in Schedule, matching TZ §4.1.14.3 and Angular.
- Default day auto-expands per TZ §4.1.14: current-week today, future-week
  first valid day, last-valid-day fallback when earlier days are out of
  window.
- Aircraft model no longer leaks into collapsed rows; shown only when
  expanded AND direct, mirroring Angular's
  operator-logo-and-model [showModel]="expanded && direct".
- Week tabs use MONTH-SHORT.* translation table so Russian renders
  "27 апр. - 3 май." instead of genitive "мая" from Intl.
- "Ранее искали" → "Вы искали" across all 9 locales (TZ §4.1.9.5).
- Sort-arrow headers compacted (inline-flex nowrap, zero gap) so labels
  stay on one line next to the chevrons.
- robots.txt allows Yandex/Googlebot/* with no Disallow (TZ §4.1.20).
- 6 non-RU/EN locales (de/es/fr/it/ja/ko) + zh were missing ~45 strings
  each; translated from Angular where present, hand-translated otherwise
  so every locale is down to the two intentional `.undefined` stubs.
This commit is contained in:
2026-04-22 17:02:31 +03:00
parent a9dacf0b97
commit 2e13d2d7ef
14 changed files with 3966 additions and 3923 deletions
@@ -34,22 +34,27 @@
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
&__sort-group {
display: inline-flex;
flex-direction: column;
gap: 1px;
gap: 0;
line-height: 0;
}
&__sort {
background: transparent;
border: 0;
padding: 1px 2px;
padding: 0;
cursor: pointer;
color: colors.$border-blue;
line-height: 0;
border-radius: 2px;
display: block;
svg { display: block; }
&:hover { color: colors.$blue; }
&--active { color: colors.$blue; }
@@ -143,21 +143,25 @@ export const DayGroupedFlightList: FC<DayGroupedFlightListProps> = ({
return g.map((day) => ({ ...day, flights: sortFlights(day.flights, sortMode) }));
}, [flights, sortMode]);
// Auto-open today's day group on first render (and when the visible
// window shifts). The user can collapse it; we never re-open after
// Auto-open the default day per TZ §4.1.14: current week expands today;
// future weeks expand the first valid day (week where only Sunday is
// valid → Sunday). The user can collapse it; we never re-open after
// that for the same date.
const [autoOpenedFor, setAutoOpenedFor] = useState<string | null>(null);
useEffect(() => {
if (groups.length === 0) return;
const now = new Date();
const todayIso = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
const todayInScope = groups.some((g) => g.date === todayIso);
if (!todayInScope || autoOpenedFor === todayIso) return;
const defaultDate = groups.some((g) => g.date === todayIso)
? todayIso
: (groups[0]?.date ?? null);
if (!defaultDate || autoOpenedFor === defaultDate) return;
setExpandedDays((prev) => {
const next = new Set(prev);
next.add(todayIso);
next.add(defaultDate);
return next;
});
setAutoOpenedFor(todayIso);
setAutoOpenedFor(defaultDate);
}, [groups, autoOpenedFor]);
// Mirror Angular `ScheduleDaysComponent.expandDefaultFlight`: once a
+9 -15
View File
@@ -15,8 +15,7 @@
* - Clicking a tab auto-scrolls (page jumps) to show the selected week.
*/
import { type FC, useEffect, useMemo, useState } from "react";
import { useLocale } from "@/i18n/useLocale.js";
import { type FC, useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "@/i18n/provider.js";
import { scheduleWindowBounds } from "@/shared/dateWindow.js";
import "./WeekTabs.scss";
@@ -46,10 +45,6 @@ function startOfWeekMonday(d: Date): Date {
return out;
}
function fmt(date: Date, fmt: Intl.DateTimeFormat): string {
return fmt.format(date).replace(/\.$/, "");
}
function ymd(d: Date): string {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, "0");
@@ -58,14 +53,13 @@ function ymd(d: Date): string {
}
export const WeekTabs: FC<WeekTabsProps> = ({ selectedMonday, onNavigate }) => {
const { language } = useLocale();
const { t } = useTranslation();
// Angular shows month abbreviated ("13 апр - 19 апр"). Build once
// per locale; the month part comes through in the locale's natural
// short form.
const dayMonthFmt = useMemo(
() => new Intl.DateTimeFormat(language, { day: "numeric", month: "short" }),
[language],
// Short month abbreviations come from `MONTH-SHORT.{1..12}`, same
// lookup table as Angular's `DatesTranslationService.getShortDateString`
// ("27 апр." / "3 май." for ru; "Apr" / "May" for en).
const shortDay = useCallback(
(d: Date) => `${d.getDate()} ${t(`MONTH-SHORT.${d.getMonth() + 1}`)}`,
[t],
);
// Build the active weeks list anchored to the schedule window
@@ -86,11 +80,11 @@ export const WeekTabs: FC<WeekTabsProps> = ({ selectedMonday, onNavigate }) => {
monday,
sunday,
ymd: ymd(monday),
label: `${fmt(monday, dayMonthFmt)} - ${fmt(sunday, dayMonthFmt)}`,
label: `${shortDay(monday)} - ${shortDay(sunday)}`,
});
}
return out;
}, [dayMonthFmt]);
}, [shortDay]);
// Derive the page that contains selectedMonday. Re-derives whenever
// selectedMonday or weeks change so navigation to a new week auto-scrolls