The code cited its plan instead of saying why: `E28 review J4`, `(R6 S3b)`, `S1 justified…`,
`deep-review round 5`. That plan lives in the private ops repo, so for every reader of this one the
citation was noise, and a sentence whose subject was the plan step ("round 2 showed…") hid its
lesson behind an id. Each one is gone and the "why" kept: a bare citation is deleted, a sentence
carrying a lesson is reworded around it ("a later attempt showed…").
Measured (`scripts/audit_metrics.py`, product code): 652 lines in 270 files carried an epic code by
the definition the next commit holds (507 / 241 by the old, two-digit-only one) -> 0. Across all
code, tests, scripts and configs: ~1100 epic-code lines plus ~320 sprint/round ids.
Behaviour unchanged, checked mechanically: every changed .py file has the same AST once docstrings
are blanked; css/sh/toml/yml/json files are identical once comments are stripped; the only
non-comment changes in TS/JS are test titles, one description string in a contract table, and five
ESLint messages, whose text is all the gates snapshot diff holds. Not touched: Markdown (docs and
the changelog keep their history), Alembic migrations, TV episode notation (`S2 · E5`), DESIGN.md
ids (`C1`, `B4`, `S3h`), tracker ids (`SEC-16`, `DX-17`).
One stale claim fixed on the way: test_hls_reaper's docstring said the player checkpoints "every
10 s whether or not it is playing", which plex/stream.py calls wrong; it now says what the code does.
92 lines
4.3 KiB
TypeScript
92 lines
4.3 KiB
TypeScript
import type { TFunction } from "i18next";
|
|
import type { PlexTrackNaming } from "./api";
|
|
|
|
// The closed vocabularies the server stores in ENGLISH — a TMDB crew job or department, an
|
|
// auto-tag, a built-in download profile, a YouTube topic, a Plex certificate's word ("Not Rated"; a
|
|
// code such as "PG-13" reads the same everywhere and falls through as stored) — named in the reader's language. The data
|
|
// stays language-neutral (it is filtered and matched on); only the NAME is translated, here, from the
|
|
// `vocab` locale area. A word the area does not hold shows as stored, so a new server value is never
|
|
// hidden — and the backend's own lists are held key-for-key to the area by backendIds.contract.
|
|
|
|
type Group = "crewJob" | "department" | "autoTag" | "profile" | "topic" | "certificate";
|
|
|
|
/** A vocabulary word's key: its letters and digits ("Health & Fitness" → "HealthFitness"). */
|
|
export function vocabKey(word: string): string {
|
|
return word.replace(/[^A-Za-z0-9]/g, "");
|
|
}
|
|
|
|
/** The i18n key of one word of `group` ("" when the word has no letters or digits) — for a caller
|
|
* whose `t` is not i18next's own (a pure builder handed a narrow `t`). */
|
|
export function vocabI18nKey(group: Group, word: string): string {
|
|
const key = vocabKey(word);
|
|
return key ? `vocab.${group}.${key}` : "";
|
|
}
|
|
|
|
/** One stored English word of `group`, in the reader's language (`fallback`, by default the word
|
|
* itself, when the area does not hold it). */
|
|
export function vocab(t: TFunction, group: Group, word: string, fallback = word): string {
|
|
const key = vocabI18nKey(group, word);
|
|
return key ? t(key, { defaultValue: fallback }) : fallback;
|
|
}
|
|
|
|
/** A download profile's name: a built-in one is seeded under an English name and named here; a user's
|
|
* own is theirs, as typed. */
|
|
export function profileName(t: TFunction, p: { name: string; is_builtin: boolean }): string {
|
|
return p.is_builtin ? vocab(t, "profile", p.name) : p.name;
|
|
}
|
|
|
|
function intlName(code: string, lang: string, type: "region" | "language"): string | undefined {
|
|
try {
|
|
return new Intl.DisplayNames([lang], { type, fallback: "none" }).of(code);
|
|
} catch {
|
|
return undefined; // not a well-formed code
|
|
}
|
|
}
|
|
|
|
/** A country from its ISO 3166 code. A code no longer in use (Yugoslavia, the Soviet Union) is
|
|
* named from `vocab.region` — Intl renames those to today's state (YU → Serbia) or cannot name them
|
|
* (XI, TMDB's Northern Ireland); `fallback` (the stored English name) when neither can. */
|
|
export function regionName(
|
|
t: TFunction,
|
|
code: string | null | undefined,
|
|
lang: string,
|
|
fallback = "",
|
|
): string {
|
|
if (!code) return fallback;
|
|
const up = code.toUpperCase();
|
|
return (
|
|
t(`vocab.region.${up}`, { defaultValue: "" }) || intlName(up, lang, "region") || fallback || up
|
|
);
|
|
}
|
|
|
|
/** A language from its BCP 47 tag ("en-US" → "American English"), capitalized to stand alone as a
|
|
* label ("magyar" → "Magyar"); `fallback` for a tag Intl cannot name ("und", a typo). */
|
|
export function languageName(tag: string | null | undefined, lang: string, fallback = ""): string {
|
|
const name = tag ? intlName(tag.replace(/_/g, "-"), lang, "language") : undefined;
|
|
if (!name || name === tag) return fallback;
|
|
return name.charAt(0).toLocaleUpperCase(lang) + name.slice(1);
|
|
}
|
|
|
|
/** An audio or subtitle track's name in the reader's language: "Angol (AC3 5.1)", "Magyar,
|
|
* kényszerített". Built from the language tag; a track without one keeps Plex's own title, and a
|
|
* track with neither is numbered. */
|
|
export function trackLabel(
|
|
t: TFunction,
|
|
track: PlexTrackNaming,
|
|
kind: "audio" | "subtitle",
|
|
lang: string,
|
|
): string {
|
|
// The language alone: Plex tags one track "en-US" and the next "en", and both are just English here.
|
|
const name = languageName(track.lang_tag?.split(/[-_]/)[0], lang);
|
|
if (!name) return track.label || t(`vocab.track.${kind}N`, { n: track.ord + 1 });
|
|
const flags = [
|
|
track.forced ? t("vocab.track.forced") : null,
|
|
track.hearing_impaired ? t("vocab.track.sdh") : null,
|
|
].filter(Boolean);
|
|
// The codec tail is technical and language-neutral but for its channel word ("AC3 Stereo").
|
|
const detail = track.detail
|
|
?.replace(/\bStereo\b/i, t("vocab.track.stereo"))
|
|
.replace(/\bMono\b/i, t("vocab.track.mono"));
|
|
return [name, ...flags].join(", ") + (detail ? ` (${detail})` : "");
|
|
}
|