Files
bonob/src/i8n.ts
2021-10-08 00:08:32 +11:00

182 lines
5.5 KiB
TypeScript

import * as A from "fp-ts/Array";
import { pipe } from "fp-ts/lib/function";
import { option as O } from "fp-ts";
import _ from "underscore";
export type LANG = "en-US" | "da-DK" | "de-DE" | "es-ES" | "fr-FR" | "it-IT" | "ja-JP" | "nb-NO" | "nl-NL" | "pt-BR" | "sv-SE" | "zh-CN"
export type SUPPORTED_LANG = "en-US" | "nl-NL";
export type KEY =
| "AppLinkMessage"
| "artists"
| "albums"
| "playlists"
| "genres"
| "random"
| "topRated"
| "recentlyAdded"
| "recentlyPlayed"
| "mostPlayed"
| "tracks"
| "success"
| "failure"
| "expectedConfig"
| "existingServiceConfig"
| "noExistingServiceRegistration"
| "register"
| "removeRegistration"
| "devices"
| "services"
| "login"
| "logInToBonob"
| "username"
| "password"
| "successfullyRegistered"
| "registrationFailed"
| "successfullyRemovedRegistration"
| "failedToRemoveRegistration"
| "invalidLinkCode"
| "loginSuccessful"
| "loginFailed"
| "noSonosDevices"
| "favourites"
| "LOVE"
| "LOVE_SUCCESS"
| "STAR"
| "UNSTAR"
| "STAR_SUCCESS"
| "UNSTAR_SUCCESS";
const translations: Record<SUPPORTED_LANG, Record<KEY, string>> = {
"en-US": {
AppLinkMessage: "Linking sonos with $BNB_SONOS_SERVICE_NAME",
artists: "Artists",
albums: "Albums",
tracks: "Tracks",
playlists: "Playlists",
genres: "Genres",
random: "Random",
topRated: "Top Rated",
recentlyAdded: "Recently added",
recentlyPlayed: "Recently played",
mostPlayed: "Most played",
success: "Success",
failure: "Failure",
expectedConfig: "Expected configuration",
existingServiceConfig: "Existing service configuration",
noExistingServiceRegistration: "No existing service registration",
register: "Register",
removeRegistration: "Remove registration",
devices: "Devices",
services: "Services",
login: "Login",
logInToBonob: "Log in to $BNB_SONOS_SERVICE_NAME",
username: "Username",
password: "Password",
successfullyRegistered: "Successfully registered",
registrationFailed: "Registration failed!",
successfullyRemovedRegistration: "Successfully removed registration",
failedToRemoveRegistration: "Failed to remove registration!",
invalidLinkCode: "Invalid linkCode!",
loginSuccessful: "Login successful!",
loginFailed: "Login failed!",
noSonosDevices: "No sonos devices",
favourites: "Favourites",
STAR: "Star",
UNSTAR: "Un-star",
STAR_SUCCESS: "Track starred",
UNSTAR_SUCCESS: "Track un-starred",
LOVE: "Love",
LOVE_SUCCESS: "Track loved"
},
"nl-NL": {
AppLinkMessage: "Sonos koppelen aan $BNB_SONOS_SERVICE_NAME",
artists: "Artiesten",
albums: "Albums",
tracks: "Nummers",
playlists: "Afspeellijsten",
genres: "Genres",
random: "Willekeurig",
topRated: "Best beoordeeld",
recentlyAdded: "Onlangs toegevoegd",
recentlyPlayed: "Onlangs afgespeeld",
mostPlayed: "Meest afgespeeld",
success: "Gelukt",
failure: "Mislukt",
expectedConfig: "Verwachte configuratie",
existingServiceConfig: "Bestaande serviceconfiguratie",
noExistingServiceRegistration: "Geen bestaande serviceregistratie",
register: "Registreren",
removeRegistration: "Verwijder registratie",
devices: "Apparaten",
services: "Services",
login: "Inloggen",
logInToBonob: "Login op $BNB_SONOS_SERVICE_NAME",
username: "Gebruikersnaam",
password: "Wachtwoord",
successfullyRegistered: "Registratie geslaagd",
registrationFailed: "Registratie mislukt!",
successfullyRemovedRegistration: "Registratie succesvol verwijderd",
failedToRemoveRegistration: "Kon registratie niet verwijderen!",
invalidLinkCode: "Ongeldige linkcode!",
loginSuccessful: "Inloggen gelukt!",
loginFailed: "Inloggen mislukt!",
noSonosDevices: "Geen Sonos-apparaten",
favourites: "Favorieten",
STAR: "Ster ",
UNSTAR: "Een ster",
STAR_SUCCESS: "Nummer met ster",
UNSTAR_SUCCESS: "Track zonder ster",
LOVE: "Liefde",
LOVE_SUCCESS: "Volg geliefd"
},
};
const translationsLookup = Object.keys(translations).reduce((lookups, lang) => {
lookups.set(lang, translations[lang as SUPPORTED_LANG]);
lookups.set(lang.toLocaleLowerCase(), translations[lang as SUPPORTED_LANG]);
lookups.set(lang.toLocaleLowerCase().split("-")[0]!, translations[lang as SUPPORTED_LANG]);
return lookups;
}, new Map<string, Record<KEY, string>>())
export const randomLang = () => _.shuffle(["en-US", "nl-NL"])[0]!;
export const asLANGs = (acceptLanguageHeader: string | undefined): LANG[] =>
pipe(
acceptLanguageHeader,
O.fromNullable,
O.map((it) => it.split(";")),
O.map((it) => it.shift() || ""),
O.map((it) =>
pipe(
it.split(","),
A.map((it) => it.trim()),
A.filter((it) => it != ""),
A.map(it => it as LANG)
)
),
O.getOrElseW(() => [])
);
export type I8N = (...langs: string[]) => Lang;
export type Lang = (key: KEY) => string;
export const langs = () => Object.keys(translations);
export const keys = (lang: SUPPORTED_LANG = "en-US") => Object.keys(translations[lang]);
export default (serviceName: string): I8N =>
(...langs: string[]): Lang => {
const langToUse =
langs.map((l) => translationsLookup.get(l as SUPPORTED_LANG)).find((it) => it) ||
translations["en-US"];
return (key: KEY) => {
const value = langToUse[key]?.replace(
"$BNB_SONOS_SERVICE_NAME",
serviceName
);
if (value) return value;
else throw `No translation found for ${langs}:${key}`;
};
};