diff --git a/front/apps/mobile/app/_layout.tsx b/front/apps/mobile/app/_layout.tsx index 43e2e916..33d83466 100644 --- a/front/apps/mobile/app/_layout.tsx +++ b/front/apps/mobile/app/_layout.tsx @@ -26,10 +26,6 @@ import { Poppins_900Black, useFonts, } from "@expo-google-fonts/poppins"; -import "@formatjs/intl-displaynames/locale-data/en"; -import "@formatjs/intl-displaynames/locale-data/fr"; -import "@formatjs/intl-displaynames/polyfill"; -import "@formatjs/intl-locale/polyfill"; import { PortalProvider } from "@gorhom/portal"; import { AccountProvider, createQueryClient, storage, useUserTheme } from "@kyoo/models"; import { SnackbarProvider, ThemeSelector } from "@kyoo/primitives"; diff --git a/front/packages/ui/package.json b/front/packages/ui/package.json index 179dd059..50686bed 100644 --- a/front/packages/ui/package.json +++ b/front/packages/ui/package.json @@ -5,11 +5,13 @@ "packageManager": "yarn@3.2.4", "dependencies": { "@kyoo/models": "workspace:^", - "@kyoo/primitives": "workspace:^" + "@kyoo/primitives": "workspace:^", + "langmap": "^0.0.16" }, "devDependencies": { "@gorhom/portal": "^1.0.14", "@shopify/flash-list": "^1.6.4", + "@types/langmap": "^0.0.3", "react-native-uuid": "^2.0.2", "typescript": "^5.4.5" }, diff --git a/front/packages/ui/src/player/video.web.tsx b/front/packages/ui/src/player/video.web.tsx index 75a6f057..66f6f877 100644 --- a/front/packages/ui/src/player/video.web.tsx +++ b/front/packages/ui/src/player/video.web.tsx @@ -293,7 +293,7 @@ const useSubtitle = ( const addSubtitle = async () => { const track: HTMLTrackElement = htmlTrack.current ?? document.createElement("track"); track.kind = "subtitles"; - track.label = value.displayName; + track.label = value.title ?? value.language ?? "Subtitle"; if (value.language) track.srclang = value.language; track.src = value.codec === "subrip" ? await toWebVtt(value.link!) : value.link!; track.className = "subtitle_container"; diff --git a/front/packages/ui/src/settings/general.tsx b/front/packages/ui/src/settings/general.tsx index bc6ca959..47192293 100644 --- a/front/packages/ui/src/settings/general.tsx +++ b/front/packages/ui/src/settings/general.tsx @@ -28,14 +28,12 @@ import Language from "@material-symbols/svg-400/outlined/language.svg"; import Android from "@material-symbols/svg-400/rounded/android.svg"; import Public from "@material-symbols/svg-400/rounded/public.svg"; +import { useLanguageName } from "../utils"; export const GeneralSettings = () => { const { t, i18n } = useTranslation(); const theme = useUserTheme("auto"); - const languages = new Intl.DisplayNames([i18n.language ?? "en"], { - type: "language", - languageDisplay: "standard", - }); + const getLanguageName = useLanguageName(); return ( @@ -65,7 +63,7 @@ export const GeneralSettings = () => { } values={["system", ...Object.keys(i18n.options.resources!)]} getLabel={(key) => - key === "system" ? t("settings.general.language.system") : languages.of(key) ?? key + key === "system" ? t("settings.general.language.system") : getLanguageName(key) ?? key } /> diff --git a/front/packages/ui/src/settings/playback.tsx b/front/packages/ui/src/settings/playback.tsx index 55450864..c8fe8171 100644 --- a/front/packages/ui/src/settings/playback.tsx +++ b/front/packages/ui/src/settings/playback.tsx @@ -20,30 +20,23 @@ import { useLocalSetting } from "@kyoo/models"; import { Select } from "@kyoo/primitives"; -import { useSetAtom } from "jotai"; import { useTranslation } from "react-i18next"; -import { PlayMode, playModeAtom } from "../player/state"; import { Preference, SettingsContainer, useSetting } from "./base"; import SubtitleLanguage from "@material-symbols/svg-400/rounded/closed_caption-fill.svg"; import PlayModeI from "@material-symbols/svg-400/rounded/display_settings-fill.svg"; import AudioLanguage from "@material-symbols/svg-400/rounded/music_note-fill.svg"; +import intl from "langmap"; +import { useLanguageName } from "../utils"; -// I gave up on finding a way to retrive this using the Intl api (probably does not exist) -// Simply copy pasted the list of languages from https://www.localeplanet.com/api/codelist.json -// biome-ignore format: way too long -const allLanguages = ["af", "agq", "ak", "am", "ar", "as", "asa", "ast", "az", "bas", "be", "bem", "bez", "bg", "bm", "bn", "bo", "br", "brx", "bs", "ca", "ccp", "ce", "cgg", "chr", "ckb", "cs", "cy", "da", "dav", "de", "dje", "dsb", "dua", "dyo", "dz", "ebu", "ee", "el", "en", "eo", "es", "et", "eu", "ewo", "fa", "ff", "fi", "fil", "fo", "fr", "fur", "fy", "ga", "gd", "gl", "gsw", "gu", "guz", "gv", "ha", "haw", "he", "hi", "hr", "hsb", "hu", "hy", "id", "ig", "ii", "is", "it", "ja", "jgo", "jmc", "ka", "kab", "kam", "kde", "kea", "khq", "ki", "kk", "kkj", "kl", "kln", "km", "kn", "ko", "kok", "ks", "ksb", "ksf", "ksh", "kw", "ky", "lag", "lb", "lg", "lkt", "ln", "lo", "lrc", "lt", "lu", "luo", "luy", "lv", "mas", "mer", "mfe", "mg", "mgh", "mgo", "mk", "ml", "mn", "mr", "ms", "mt", "mua", "my", "mzn", "naq", "nb", "nd", "nds", "ne", "nl", "nmg", "nn", "nnh", "nus", "nyn", "om", "or", "os", "pa", "pl", "ps", "pt", "qu", "rm", "rn", "ro", "rof", "ru", "rw", "rwk", "sah", "saq", "sbp", "se", "seh", "ses", "sg", "shi", "si", "sk", "sl", "smn", "sn", "so", "sq", "sr", "sv", "sw", "ta", "te", "teo", "tg", "th", "ti", "to", "tr", "tt", "twq", "tzm", "ug", "uk", "ur", "uz", "vai", "vi", "vun", "wae", "wo", "xog", "yav", "yi", "yo", "yue", "zgh", "zh", "zu",]; +const allLanguages = Object.keys(intl).filter((x) => !x.includes("-") && !x.includes("@")); export const PlaybackSettings = () => { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const [playMode, setDefaultPlayMode] = useLocalSetting("playmode", "direct"); - const setCurrentPlayMode = useSetAtom(playModeAtom); const [audio, setAudio] = useSetting("audioLanguage")!; const [subtitle, setSubtitle] = useSetting("subtitleLanguage")!; - const languages = new Intl.DisplayNames([i18n.language ?? "en"], { - type: "language", - languageDisplay: "standard", - }); + const getLanguageName = useLanguageName(); return ( @@ -57,7 +50,7 @@ export const PlaybackSettings = () => { value={playMode} onValueChange={(value) => setDefaultPlayMode(value)} values={["direct", "auto"]} - getLabel={(key) => t(`player.${key}`)} + getLabel={(key) => t(`player.${key}` as any)} /> { onValueChange={(value) => setAudio(value)} values={["default", ...allLanguages]} getLabel={(key) => - key === "default" ? t("mediainfo.default") : languages.of(key) ?? key + key === "default" ? t("mediainfo.default") : getLanguageName(key) ?? key } /> @@ -90,7 +83,7 @@ export const PlaybackSettings = () => { ? t("settings.playback.subtitleLanguage.none") : key === "default" ? t("mediainfo.default") - : languages.of(key) ?? key + : getLanguageName(key) ?? key } /> diff --git a/front/packages/ui/src/utils.ts b/front/packages/ui/src/utils.ts index 26ea0b75..89320206 100644 --- a/front/packages/ui/src/utils.ts +++ b/front/packages/ui/src/utils.ts @@ -1,12 +1,15 @@ import type { Track } from "@kyoo/models"; -import { useTranslation } from "react-i18next"; +import intl from "langmap"; + +export const useLanguageName = () => { + return (lang: string) => intl[lang]?.nativeName; +}; export const useDisplayName = () => { - const { i18n } = useTranslation(); + const getLanguageName = useLanguageName(); return (sub: Track) => { - const languageNames = new Intl.DisplayNames([i18n.language ?? "en"], { type: "language" }); - const lng = sub.language ? languageNames.of(sub.language) : undefined; + const lng = sub.language ? getLanguageName(sub.language) : null; if (lng && sub.title && sub.title !== lng) return `${lng} - ${sub.title}`; if (lng) return lng; diff --git a/front/yarn.lock b/front/yarn.lock index 34410f6b..929716fe 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -3333,8 +3333,10 @@ __metadata: "@kyoo/models": "workspace:^" "@kyoo/primitives": "workspace:^" "@shopify/flash-list": ^1.6.4 + "@types/langmap": ^0.0.3 expo-file-system: ^17.0.1 expo-router: ^3.5.14 + langmap: ^0.0.16 react-native-uuid: ^2.0.2 typescript: ^5.4.5 peerDependencies: @@ -5261,6 +5263,13 @@ __metadata: languageName: node linkType: hard +"@types/langmap@npm:^0.0.3": + version: 0.0.3 + resolution: "@types/langmap@npm:0.0.3" + checksum: 20a38ed78a48d38ba51782d3683b3302d3cf919c601f3b23dafc8e955037887726088007e9ead4a95927927ac67bb255ff39a17c22a1ba3012fa30dd1a796e0a + languageName: node + linkType: hard + "@types/node-forge@npm:^1.3.0": version: 1.3.11 resolution: "@types/node-forge@npm:1.3.11" @@ -9611,6 +9620,13 @@ __metadata: languageName: unknown linkType: soft +"langmap@npm:^0.0.16": + version: 0.0.16 + resolution: "langmap@npm:0.0.16" + checksum: ea409e502ede3492f2161e79c59394e6642d34706fdcae7a5df2116eda2110aa53b94f11282fc354f3fe5832f9e8783572471b3e28dd05899b1efe442122b7cc + languageName: node + linkType: hard + "leven@npm:^3.1.0": version: 3.1.0 resolution: "leven@npm:3.1.0"