Fall back to English TMDB titles when Dutch is missing.
Prevents German (and other) originals from being stored as the display title when no nl-NL translation exists.
This commit is contained in:
parent
93d96d7bb1
commit
40a5ecd435
3 changed files with 244 additions and 32 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
"dev": "tsx watch src/app.ts",
|
"dev": "tsx watch src/app.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node dist/app.js",
|
"start": "node dist/app.js",
|
||||||
"test": "tsx src/metadata/filename-parser.test.ts && tsx src/google-play/service.test.ts && tsx src/viewer/iptv-categories.test.ts",
|
"test": "tsx src/metadata/filename-parser.test.ts && tsx src/metadata/title-locale.test.ts && tsx src/google-play/service.test.ts && tsx src/viewer/iptv-categories.test.ts",
|
||||||
"db:generate": "prisma generate",
|
"db:generate": "prisma generate",
|
||||||
"db:migrate": "prisma migrate deploy",
|
"db:migrate": "prisma migrate deploy",
|
||||||
"db:migrate:dev": "prisma migrate dev",
|
"db:migrate:dev": "prisma migrate dev",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ interface TmdbSearchResult {
|
||||||
id: number;
|
id: number;
|
||||||
title?: string;
|
title?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
original_title?: string;
|
||||||
|
original_name?: string;
|
||||||
|
original_language?: string;
|
||||||
release_date?: string;
|
release_date?: string;
|
||||||
first_air_date?: string;
|
first_air_date?: string;
|
||||||
overview?: string;
|
overview?: string;
|
||||||
|
|
@ -33,6 +36,59 @@ const TMDB_STILL_BASE = "https://image.tmdb.org/t/p/w300";
|
||||||
const TMDB_LOGO_BASE = "https://image.tmdb.org/t/p/w300";
|
const TMDB_LOGO_BASE = "https://image.tmdb.org/t/p/w300";
|
||||||
const TMDB_BACKDROP_BASE = "https://image.tmdb.org/t/p/original";
|
const TMDB_BACKDROP_BASE = "https://image.tmdb.org/t/p/original";
|
||||||
const TMDB_LANG = "nl-NL";
|
const TMDB_LANG = "nl-NL";
|
||||||
|
const TMDB_LANG_EN = "en-US";
|
||||||
|
|
||||||
|
function isDutchLanguage(lang?: string | null): boolean {
|
||||||
|
const l = (lang || "").toLowerCase();
|
||||||
|
return l === "nl" || l.startsWith("nl-");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TMDB met language=nl-NL zet `title` op `original_title` als er geen NL-vertaling is.
|
||||||
|
* Dan liever Engels (of original als EN ontbreekt).
|
||||||
|
*/
|
||||||
|
export function preferNlOrEnglishTitle(opts: {
|
||||||
|
localizedTitle?: string | null;
|
||||||
|
originalTitle?: string | null;
|
||||||
|
originalLanguage?: string | null;
|
||||||
|
englishTitle?: string | null;
|
||||||
|
}): string {
|
||||||
|
const localized = opts.localizedTitle?.trim() || "";
|
||||||
|
const original = opts.originalTitle?.trim() || "";
|
||||||
|
const english = opts.englishTitle?.trim() || "";
|
||||||
|
if (isDutchLanguage(opts.originalLanguage)) {
|
||||||
|
return localized || original || english || "Onbekend";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
localized &&
|
||||||
|
original &&
|
||||||
|
normalizeMatchTitle(localized) !== normalizeMatchTitle(original)
|
||||||
|
) {
|
||||||
|
return localized;
|
||||||
|
}
|
||||||
|
if (english) return english;
|
||||||
|
return localized || original || "Onbekend";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEnglishLanguage(lang?: string | null): boolean {
|
||||||
|
const l = (lang || "").toLowerCase();
|
||||||
|
return l === "en" || l.startsWith("en-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function needsEnglishTitleFallback(
|
||||||
|
localizedTitle?: string | null,
|
||||||
|
originalTitle?: string | null,
|
||||||
|
originalLanguage?: string | null
|
||||||
|
): boolean {
|
||||||
|
if (isDutchLanguage(originalLanguage)) return false;
|
||||||
|
if (isEnglishLanguage(originalLanguage)) return false;
|
||||||
|
const localized = localizedTitle?.trim() || "";
|
||||||
|
const original = originalTitle?.trim() || "";
|
||||||
|
if (!localized) return true;
|
||||||
|
if (!original) return false;
|
||||||
|
// Geen NL-vertaling → TMDB herhaalt de original (vaak DE/FR/…)
|
||||||
|
return normalizeMatchTitle(localized) === normalizeMatchTitle(original);
|
||||||
|
}
|
||||||
|
|
||||||
function sleep(ms: number): Promise<void> {
|
function sleep(ms: number): Promise<void> {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
@ -79,6 +135,7 @@ const METAHUB_LOGO = (imdbId: string) =>
|
||||||
type TmdbMeta = {
|
type TmdbMeta = {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
|
originalTitle?: string;
|
||||||
year?: number;
|
year?: number;
|
||||||
overview?: string;
|
overview?: string;
|
||||||
posterUrl?: string;
|
posterUrl?: string;
|
||||||
|
|
@ -1379,24 +1436,51 @@ export class MetadataService {
|
||||||
return found ? [found] : [];
|
return found ? [found] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const path = type === "movie" ? "search/movie" : "search/tv";
|
||||||
|
const base = {
|
||||||
api_key: this.tmdbApiKey,
|
api_key: this.tmdbApiKey,
|
||||||
query: q,
|
query: q,
|
||||||
language: TMDB_LANG,
|
|
||||||
include_adult: "false",
|
include_adult: "false",
|
||||||
});
|
};
|
||||||
const path = type === "movie" ? "search/movie" : "search/tv";
|
const [nlRes, enRes] = await Promise.all([
|
||||||
const res = await fetch(`https://api.themoviedb.org/3/${path}?${params}`);
|
fetch(
|
||||||
if (!res.ok) return [];
|
`https://api.themoviedb.org/3/${path}?${new URLSearchParams({
|
||||||
const data = (await res.json()) as TmdbSearchResult;
|
...base,
|
||||||
|
language: TMDB_LANG,
|
||||||
|
})}`
|
||||||
|
),
|
||||||
|
fetch(
|
||||||
|
`https://api.themoviedb.org/3/${path}?${new URLSearchParams({
|
||||||
|
...base,
|
||||||
|
language: TMDB_LANG_EN,
|
||||||
|
})}`
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
if (!nlRes.ok) return [];
|
||||||
|
const data = (await nlRes.json()) as TmdbSearchResult;
|
||||||
|
const enById = new Map<number, TmdbSearchResult["results"][number]>();
|
||||||
|
if (enRes.ok) {
|
||||||
|
const enData = (await enRes.json()) as TmdbSearchResult;
|
||||||
|
for (const hit of enData.results ?? []) enById.set(hit.id, hit);
|
||||||
|
}
|
||||||
return (data.results ?? []).slice(0, 12).map((item) => {
|
return (data.results ?? []).slice(0, 12).map((item) => {
|
||||||
|
const en = enById.get(item.id);
|
||||||
const date = type === "movie" ? item.release_date : item.first_air_date;
|
const date = type === "movie" ? item.release_date : item.first_air_date;
|
||||||
const year = date ? parseInt(date.slice(0, 4), 10) : null;
|
const year = date ? parseInt(date.slice(0, 4), 10) : null;
|
||||||
|
const localized = type === "movie" ? item.title : item.name;
|
||||||
|
const original = type === "movie" ? item.original_title : item.original_name;
|
||||||
|
const english = type === "movie" ? en?.title : en?.name;
|
||||||
|
const overview = item.overview?.trim() || en?.overview?.trim() || null;
|
||||||
return {
|
return {
|
||||||
tmdbId: item.id,
|
tmdbId: item.id,
|
||||||
title: (type === "movie" ? item.title : item.name) || "Onbekend",
|
title: preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: localized,
|
||||||
|
originalTitle: original,
|
||||||
|
originalLanguage: item.original_language,
|
||||||
|
englishTitle: english,
|
||||||
|
}),
|
||||||
year: Number.isFinite(year) ? year : null,
|
year: Number.isFinite(year) ? year : null,
|
||||||
overview: item.overview || null,
|
overview,
|
||||||
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : null,
|
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : null,
|
||||||
imdbId: null,
|
imdbId: null,
|
||||||
};
|
};
|
||||||
|
|
@ -1768,11 +1852,29 @@ export class MetadataService {
|
||||||
const item =
|
const item =
|
||||||
type === "movie" ? data.movie_results?.[0] : data.tv_results?.[0];
|
type === "movie" ? data.movie_results?.[0] : data.tv_results?.[0];
|
||||||
if (!item) return null;
|
if (!item) return null;
|
||||||
|
const meta =
|
||||||
|
type === "movie"
|
||||||
|
? await this.getTmdbMovieDetails(item.id)
|
||||||
|
: await this.getTmdbSeriesDetails(item.id);
|
||||||
|
if (meta) {
|
||||||
|
return {
|
||||||
|
tmdbId: meta.id,
|
||||||
|
title: meta.title,
|
||||||
|
year: meta.year ?? null,
|
||||||
|
overview: meta.overview || null,
|
||||||
|
posterUrl: meta.posterUrl || null,
|
||||||
|
imdbId: meta.imdbId || imdbId,
|
||||||
|
};
|
||||||
|
}
|
||||||
const date = type === "movie" ? item.release_date : item.first_air_date;
|
const date = type === "movie" ? item.release_date : item.first_air_date;
|
||||||
const year = date ? parseInt(date.slice(0, 4), 10) : null;
|
const year = date ? parseInt(date.slice(0, 4), 10) : null;
|
||||||
return {
|
return {
|
||||||
tmdbId: item.id,
|
tmdbId: item.id,
|
||||||
title: (type === "movie" ? item.title : item.name) || "Onbekend",
|
title: preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: type === "movie" ? item.title : item.name,
|
||||||
|
originalTitle: type === "movie" ? item.original_title : item.original_name,
|
||||||
|
originalLanguage: item.original_language,
|
||||||
|
}),
|
||||||
year: Number.isFinite(year) ? year : null,
|
year: Number.isFinite(year) ? year : null,
|
||||||
overview: item.overview || null,
|
overview: item.overview || null,
|
||||||
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : null,
|
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : null,
|
||||||
|
|
@ -2004,6 +2106,7 @@ export class MetadataService {
|
||||||
const releaseDate = parseTmdbDate(tmdb.releaseDate);
|
const releaseDate = parseTmdbDate(tmdb.releaseDate);
|
||||||
const data = {
|
const data = {
|
||||||
title: tmdb.title,
|
title: tmdb.title,
|
||||||
|
...(tmdb.originalTitle ? { originalTitle: tmdb.originalTitle } : {}),
|
||||||
year: tmdb.year,
|
year: tmdb.year,
|
||||||
overview: tmdb.overview,
|
overview: tmdb.overview,
|
||||||
posterUrl: tmdb.posterUrl,
|
posterUrl: tmdb.posterUrl,
|
||||||
|
|
@ -2274,20 +2377,50 @@ export class MetadataService {
|
||||||
const item = (await res.json()) as {
|
const item = (await res.json()) as {
|
||||||
id: number;
|
id: number;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
original_title?: string;
|
||||||
|
original_language?: string;
|
||||||
overview?: string;
|
overview?: string;
|
||||||
release_date?: string;
|
release_date?: string;
|
||||||
poster_path?: string;
|
poster_path?: string;
|
||||||
backdrop_path?: string;
|
backdrop_path?: string;
|
||||||
adult?: boolean;
|
adult?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let englishTitle: string | undefined;
|
||||||
|
let englishOverview: string | undefined;
|
||||||
|
const wantEnTitle = needsEnglishTitleFallback(
|
||||||
|
item.title,
|
||||||
|
item.original_title,
|
||||||
|
item.original_language
|
||||||
|
);
|
||||||
|
const wantEnOverview = !item.overview?.trim();
|
||||||
|
if (wantEnTitle || wantEnOverview) {
|
||||||
|
const enParams = new URLSearchParams({
|
||||||
|
api_key: this.tmdbApiKey,
|
||||||
|
language: TMDB_LANG_EN,
|
||||||
|
});
|
||||||
|
const enRes = await fetch(`https://api.themoviedb.org/3/movie/${tmdbId}?${enParams}`);
|
||||||
|
if (enRes.ok) {
|
||||||
|
const en = (await enRes.json()) as { title?: string; overview?: string };
|
||||||
|
englishTitle = en.title;
|
||||||
|
englishOverview = en.overview;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const imdbId = await this.fetchTmdbMovieImdbId(tmdbId);
|
const imdbId = await this.fetchTmdbMovieImdbId(tmdbId);
|
||||||
const meta: TmdbMeta = {
|
const meta: TmdbMeta = {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
title: item.title || "Onbekend",
|
title: preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: item.title,
|
||||||
|
originalTitle: item.original_title,
|
||||||
|
originalLanguage: item.original_language,
|
||||||
|
englishTitle,
|
||||||
|
}),
|
||||||
|
originalTitle: item.original_title?.trim() || undefined,
|
||||||
year: item.release_date
|
year: item.release_date
|
||||||
? parseInt(item.release_date.slice(0, 4), 10)
|
? parseInt(item.release_date.slice(0, 4), 10)
|
||||||
: fallbackYear,
|
: fallbackYear,
|
||||||
overview: item.overview || undefined,
|
overview: item.overview?.trim() || englishOverview?.trim() || undefined,
|
||||||
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : undefined,
|
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : undefined,
|
||||||
backdropUrl: item.backdrop_path
|
backdropUrl: item.backdrop_path
|
||||||
? `${TMDB_BACKDROP_BASE}${item.backdrop_path}`
|
? `${TMDB_BACKDROP_BASE}${item.backdrop_path}`
|
||||||
|
|
@ -2322,29 +2455,26 @@ export class MetadataService {
|
||||||
numberOfSeasons: number;
|
numberOfSeasons: number;
|
||||||
} | null> {
|
} | null> {
|
||||||
if (!this.tmdbApiKey || !Number.isFinite(tmdbId)) return null;
|
if (!this.tmdbApiKey || !Number.isFinite(tmdbId)) return null;
|
||||||
|
const meta = await this.getTmdbSeriesDetails(tmdbId);
|
||||||
|
if (!meta) return null;
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
api_key: this.tmdbApiKey,
|
api_key: this.tmdbApiKey,
|
||||||
language: TMDB_LANG,
|
language: TMDB_LANG,
|
||||||
});
|
});
|
||||||
const res = await fetch(`https://api.themoviedb.org/3/tv/${tmdbId}?${params}`);
|
const res = await fetch(`https://api.themoviedb.org/3/tv/${tmdbId}?${params}`);
|
||||||
if (!res.ok) return null;
|
let numberOfSeasons = 0;
|
||||||
const item = (await res.json()) as {
|
if (res.ok) {
|
||||||
id: number;
|
const item = (await res.json()) as { number_of_seasons?: number };
|
||||||
name?: string;
|
numberOfSeasons = Math.max(0, item.number_of_seasons ?? 0);
|
||||||
overview?: string;
|
}
|
||||||
first_air_date?: string;
|
|
||||||
poster_path?: string;
|
|
||||||
number_of_seasons?: number;
|
|
||||||
};
|
|
||||||
const imdbId = (await this.fetchTmdbSeriesImdbId(tmdbId)) ?? null;
|
|
||||||
return {
|
return {
|
||||||
tmdbId: item.id,
|
tmdbId: meta.id,
|
||||||
title: item.name || "Onbekend",
|
title: meta.title,
|
||||||
year: item.first_air_date ? parseInt(item.first_air_date.slice(0, 4), 10) : null,
|
year: meta.year ?? null,
|
||||||
overview: item.overview || null,
|
overview: meta.overview || null,
|
||||||
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : null,
|
posterUrl: meta.posterUrl || null,
|
||||||
imdbId,
|
imdbId: meta.imdbId ?? null,
|
||||||
numberOfSeasons: Math.max(0, item.number_of_seasons ?? 0),
|
numberOfSeasons,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2423,21 +2553,51 @@ export class MetadataService {
|
||||||
const item = (await res.json()) as {
|
const item = (await res.json()) as {
|
||||||
id: number;
|
id: number;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
original_name?: string;
|
||||||
|
original_language?: string;
|
||||||
overview?: string;
|
overview?: string;
|
||||||
first_air_date?: string;
|
first_air_date?: string;
|
||||||
poster_path?: string;
|
poster_path?: string;
|
||||||
backdrop_path?: string;
|
backdrop_path?: string;
|
||||||
adult?: boolean;
|
adult?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let englishTitle: string | undefined;
|
||||||
|
let englishOverview: string | undefined;
|
||||||
|
const wantEnTitle = needsEnglishTitleFallback(
|
||||||
|
item.name,
|
||||||
|
item.original_name,
|
||||||
|
item.original_language
|
||||||
|
);
|
||||||
|
const wantEnOverview = !item.overview?.trim();
|
||||||
|
if (wantEnTitle || wantEnOverview) {
|
||||||
|
const enParams = new URLSearchParams({
|
||||||
|
api_key: this.tmdbApiKey,
|
||||||
|
language: TMDB_LANG_EN,
|
||||||
|
});
|
||||||
|
const enRes = await fetch(`https://api.themoviedb.org/3/tv/${tmdbId}?${enParams}`);
|
||||||
|
if (enRes.ok) {
|
||||||
|
const en = (await enRes.json()) as { name?: string; overview?: string };
|
||||||
|
englishTitle = en.name;
|
||||||
|
englishOverview = en.overview;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const logoUrl = await this.fetchTmdbSeriesLogo(tmdbId);
|
const logoUrl = await this.fetchTmdbSeriesLogo(tmdbId);
|
||||||
const imdbId = await this.fetchTmdbSeriesImdbId(tmdbId);
|
const imdbId = await this.fetchTmdbSeriesImdbId(tmdbId);
|
||||||
const meta: TmdbMeta = {
|
const meta: TmdbMeta = {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
title: item.name || "Onbekend",
|
title: preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: item.name,
|
||||||
|
originalTitle: item.original_name,
|
||||||
|
originalLanguage: item.original_language,
|
||||||
|
englishTitle,
|
||||||
|
}),
|
||||||
|
originalTitle: item.original_name?.trim() || undefined,
|
||||||
year: item.first_air_date
|
year: item.first_air_date
|
||||||
? parseInt(item.first_air_date.slice(0, 4), 10)
|
? parseInt(item.first_air_date.slice(0, 4), 10)
|
||||||
: undefined,
|
: undefined,
|
||||||
overview: item.overview || undefined,
|
overview: item.overview?.trim() || englishOverview?.trim() || undefined,
|
||||||
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : undefined,
|
posterUrl: item.poster_path ? `${TMDB_IMAGE_BASE}${item.poster_path}` : undefined,
|
||||||
backdropUrl: item.backdrop_path
|
backdropUrl: item.backdrop_path
|
||||||
? `${TMDB_BACKDROP_BASE}${item.backdrop_path}`
|
? `${TMDB_BACKDROP_BASE}${item.backdrop_path}`
|
||||||
|
|
@ -2524,6 +2684,7 @@ export class MetadataService {
|
||||||
where: { id: movieId },
|
where: { id: movieId },
|
||||||
data: {
|
data: {
|
||||||
title: tmdb.title,
|
title: tmdb.title,
|
||||||
|
...(tmdb.originalTitle ? { originalTitle: tmdb.originalTitle } : {}),
|
||||||
overview: tmdb.overview,
|
overview: tmdb.overview,
|
||||||
posterUrl: tmdb.posterUrl,
|
posterUrl: tmdb.posterUrl,
|
||||||
backdropUrl: tmdb.backdropUrl,
|
backdropUrl: tmdb.backdropUrl,
|
||||||
|
|
|
||||||
51
apps/master-api/src/metadata/title-locale.test.ts
Normal file
51
apps/master-api/src/metadata/title-locale.test.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { preferNlOrEnglishTitle } from "./service";
|
||||||
|
|
||||||
|
function assert(condition: unknown, message: string): asserts condition {
|
||||||
|
if (!condition) throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
assert(
|
||||||
|
preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: "Het Neverending Story",
|
||||||
|
originalTitle: "Die unendliche Geschichte II",
|
||||||
|
originalLanguage: "de",
|
||||||
|
englishTitle: "The NeverEnding Story II: The Next Chapter",
|
||||||
|
}) === "Het Neverending Story",
|
||||||
|
"should keep real NL translation"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: "Die unendliche Geschichte II – Auf der Suche nach Phantásien",
|
||||||
|
originalTitle: "Die unendliche Geschichte II – Auf der Suche nach Phantásien",
|
||||||
|
originalLanguage: "de",
|
||||||
|
englishTitle: "The NeverEnding Story II: The Next Chapter",
|
||||||
|
}) === "The NeverEnding Story II: The Next Chapter",
|
||||||
|
"should fall back to English when NL equals original"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: "Turks fruit",
|
||||||
|
originalTitle: "Turks fruit",
|
||||||
|
originalLanguage: "nl",
|
||||||
|
englishTitle: "Turkish Delight",
|
||||||
|
}) === "Turks fruit",
|
||||||
|
"should keep Dutch originals"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
preferNlOrEnglishTitle({
|
||||||
|
localizedTitle: "The Matrix",
|
||||||
|
originalTitle: "The Matrix",
|
||||||
|
originalLanguage: "en",
|
||||||
|
englishTitle: "The Matrix",
|
||||||
|
}) === "The Matrix",
|
||||||
|
"should keep English originals"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("title-locale tests passed");
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
Loading…
Reference in a new issue