Files
flights_web/src/ui/layout/PageTabs.tsx
T
gnezim ce2ca4a689 i18n: BCP-47 URL locales + complete EN translations
- URL surface now matches Angular: `/ru-ru/`, `/en-us/`, `/zh-cn/`, …
  (BCP-47). Bare short codes still work — the [lang]/layout auto-
  promotes them with a replace navigation. Internally everything that
  needs the short language (i18n file lookup, API path segment,
  Accept-Language header, dictionary `title[lang]` key, Intl
  formatters) reads it through the new `useLocale()` hook, which
  returns both `locale` (BCP-47) and `language` (short).
- ApiClient.locale is now mutable and is updated from the [lang]
  layout whenever the URL locale changes — was hard-coded to "ru" in
  the root layout before, so backend responses for /en/... still came
  back in Russian. Cities / airports / flight statuses now arrive in
  the active language.
- All 21 empty EN translation keys filled in (AIRPLANE.*, BOARD.
  PREVIOUS-FLIGHT, SCHEDULE.FILE-NAME, SEO.SCHEDULE.*, SEO.FLIGHTS-
  MAP.*, SHARED.FLIGHT-TRANSFER-PLURAL-*, SHARED.WEEK_FORMAT-WRONG)
  so /en-us renders without falling back to raw keys.
- Added BOARD.LOAD-FAILED-TITLE / -MESSAGE keys (RU + EN) and removed
  the three hardcoded Russian error strings from the search-page
  error card.
- FlightStatus now reads `FLIGHT-STATUSES.{Status}` from i18n instead
  of hardcoding the Russian labels.
- FlightCard's OperatorLogo now picks the en/ru carrier-logo variant
  from `useLocale().language` instead of always passing "ru" — the
  Aeroflot/Rossiya logos display in the active language where
  variants exist.
- registerPrimeLocales(): all 9 supported languages get a PrimeReact
  `addLocale` entry at module load (RU + EN hand-curated, others built
  from Intl). Calendar/AutoComplete widgets switch with the URL.
- ErrorBoundary catches outside the i18n provider, so it now ships
  its own minimal localised string table keyed off the URL locale —
  no more "Something went wrong" leaking on the Russian site.
- Hreflang URLs now emit BCP-47 (`/en-us/...`) while `hreflang="en"`
  stays the short Google-friendly form.
- Datetime helpers accept either short or BCP-47 locale (`isRussianLocale`)
  so callers can pass through whatever the route hands them.
2026-04-19 17:36:24 +03:00

64 lines
1.8 KiB
TypeScript

/**
* Page navigation tabs matching the Angular `flights-page-tabs` component.
*
* Renders "Online Timetable" / "Schedule" / "Flights Map" tab buttons
* using the same `.tabs` class names as the Angular version.
*/
import type { FC } from "react";
import { Link } from "@modern-js/runtime/router";
import { useTranslation } from "@/i18n/provider.js";
import { useLocale } from "@/i18n/useLocale.js";
import { useFeatureFlag } from "@/features/flights-map/hooks/useFeatureFlag.js";
import "./PageTabs.scss";
export type ViewType = "onlineboard" | "schedule" | "flights-map";
export interface PageTabsProps {
viewType: ViewType;
showFlightsMap?: boolean;
}
export const PageTabs: FC<PageTabsProps> = ({
viewType,
showFlightsMap,
}) => {
const flightsMapEnabled = useFeatureFlag("flightsMap");
const showMap = showFlightsMap ?? flightsMapEnabled;
const { t } = useTranslation();
const { locale } = useLocale();
return (
<div className="tabs">
<div className="tabs__row">
<Link
className={`tabs__tab${viewType === "onlineboard" ? " active" : ""}`}
to={`/${locale}/onlineboard`}
data-testid="onlineboard-tab"
>
{t("BOARD.TITLE")}
</Link>
<Link
className={`tabs__tab${viewType === "schedule" ? " active" : ""}`}
to={`/${locale}/schedule`}
data-testid="schedule-tab"
>
{t("SCHEDULE.TITLE-TAB")}
</Link>
</div>
{showMap && (
<div className="tabs__row">
<Link
className={`tabs__tab tabs__tab--full${viewType === "flights-map" ? " active" : ""}`}
to={`/${locale}/flights-map`}
data-testid="flights-map-tab"
>
{t("FLIGHTS-MAP.TITLE")}
</Link>
</div>
)}
</div>
);
};