add language picker

This commit is contained in:
Blobadoodle 2023-04-08 16:35:23 +01:00
parent cf6dcfe7a6
commit 1ff5940375
7 changed files with 103 additions and 5 deletions

View File

@ -862,4 +862,37 @@ input[type="checkbox"] {
height: 6rem;
width: 6rem;
}
}
.dropdown-select {
display: inline-flex;
flex-direction: row;
align-items: center;
flex-wrap: nowrap;
/* padding: 0.55rem 1rem 0.8rem 0.7rem; */
width: fit-content;
background: var(--accent-button-bg);
font-size: 0.9rem;
}
.dropdown-select label {
margin: 0.55rem var(--padding-1) 0.8rem 0.7rem;
}
.dropdown-select select {
background: var(--accent-button-bg);
font-family: var(--font-mono);
color: var(--accent);
line-height: 1.35rem;
height: 2.65rem;
border: none;
}
.dropdown-select select:hover {
background: var(--accent-hover);
}
.dropdown-select select option:hover {
background: var(--accent-hover);
}
.dropdown-select select option {
line-height: 0.9rem;
height: 2.25rem;
}

View File

@ -20,6 +20,7 @@ let checkboxes = ["disableTikTokWatermark", "fullTikTokAudio", "muteAudio"];
let exceptions = { // used for mobile devices
"vQuality": "720"
}
let dropdowns = ["language"]
function eid(id) {
return document.getElementById(id)
@ -30,6 +31,19 @@ function sGet(id) {
function sSet(id, value) {
localStorage.setItem(id, value)
}
function setCookie(id, value, expire = 730, path = "/") { // by default expire in 2 years
const d = new Date();
d.setTime(d.getTime() + (expire * 24 * 60 * 60 * 1000));
document.cookie = `${id}=${value};expires=${d.toUTCString()};path=${path}`;
}
function getCookie(id) {
const cookies = {};
for(let i of document.cookie.split(';')) {
const [key, value] = i.split('=');
cookies[key] = value;
}
return cookies[id];
}
function enable(id) {
eid(id).dataset.enabled = "true";
}
@ -248,6 +262,15 @@ function checkbox(action) {
}
action === "disableChangelog" && sGet(action) === "true" ? notificationCheck("disable") : notificationCheck();
}
function dropdownSelect(action) {
let value = eid(`${action}-select`).value;
if(action === "language") { // language has to be a cookie because the server needs to read the value
setCookie(action, value);
window.location.reload();
} else {
sSet(action, value)
}
}
function loadSettings() {
try {
if (typeof(navigator.clipboard.readText) == "undefined") throw new Error();
@ -268,6 +291,13 @@ function loadSettings() {
for (let i in switchers) {
changeSwitcher(i, sGet(i))
}
for (let i of dropdowns) {
if(i == 'language') {
eid(`${i}-select`).value = getCookie(i) || document.documentElement.lang;
} else{
eid(`${i}-select`).value = sGet(i);
}
}
}
function changeButton(type, text) {
switch (type) {
@ -443,4 +473,4 @@ eid("url-input-area").addEventListener("keyup", (event) => {
document.onkeydown = (event) => {
if (event.key === "Tab" || event.ctrlKey) eid("url-input-area").focus();
if (event.key === 'Escape') hideAllPopups();
}
}

View File

@ -117,6 +117,8 @@
"SettingsDubDefault": "original",
"SettingsDubAuto": "auto",
"SettingsVimeoPrefer": "vimeo downloads type",
"SettingsVimeoPreferDescription": "progressive: direct file link to vimeo's cdn. max quality is 1080p.\ndash: video and audio are merged by {appName} into one file. max quality is 4k.\n\npick \"progressive\" if you want best editor/player/social media compatibility. if progressive download isn't available, dash is used instead."
"SettingsVimeoPreferDescription": "progressive: direct file link to vimeo's cdn. max quality is 1080p.\ndash: video and audio are merged by {appName} into one file. max quality is 4k.\n\npick \"progressive\" if you want best editor/player/social media compatibility. if progressive download isn't available, dash is used instead.",
"SettingsAccessibilitySubtitle": "accessibility",
"SettingsAccessibilityLanguage": "interface language:"
}
}

View File

@ -6,6 +6,7 @@ const locPath = './src/localization/languages'
let loc = {}
let languages = [];
let languageNames = [];
export function loadLoc() {
fs.readdir(locPath, (err, files) => {
@ -13,6 +14,7 @@ export function loadLoc() {
files.forEach(file => {
loc[file.split('.')[0]] = loadJson(`${locPath}/${file}`);
languages.push(file.split('.')[0])
languageNames.push({value: file.split('.')[0], name: loc[file.split('.')[0]].name })
});
})
}
@ -46,3 +48,4 @@ export default function(lang, string, replacement) {
}
}
export const languageList = languages;
export const languagePickerNames = languageNames;

View File

@ -173,3 +173,16 @@ export function celebrationsEmoji() {
let dm = `${n[1]}-${n[2]}`;
return Object.keys(celebrations).includes(dm) ? celebrations[dm] : "🐲";
}
export function dropdownSelect(label, action, options) {
let items = `
<div class="dropdown-select">
<label for="${action}-select">${label}</label>
<select name="${action}-select" id="${action}-select" onchange="dropdownSelect('${action}');">`;
for (let i of options) {
items += `<option value="${i.value}">${i.name}</option>`;
}
items += '</select></div>';
return items;
}

View File

@ -1,7 +1,7 @@
import { backdropLink, celebrationsEmoji, checkbox, collapsibleList, explanation, footerButtons, multiPagePopup, popup, popupWithBottomButtons, sep, settingsCategory, switcher, socialLink } from "./elements.js";
import { backdropLink, celebrationsEmoji, checkbox, collapsibleList, explanation, footerButtons, multiPagePopup, popup, popupWithBottomButtons, sep, settingsCategory, switcher, socialLink, dropdownSelect } from "./elements.js";
import { services as s, appName, authorInfo, version, repo, donations, supportedAudio } from "../config.js";
import { getCommitInfo } from "../sub/currentCommit.js";
import loc from "../../localization/manager.js";
import loc, { languagePickerNames } from "../../localization/manager.js";
import emoji from "../emoji.js";
import changelogManager from "../changelog/changelogManager.js";
@ -319,6 +319,10 @@ export default function(obj) {
name: "miscellaneous",
title: t('Miscellaneous'),
body: checkbox("disableChangelog", t('SettingsDisableNotifications')) + `${!isIOS ? checkbox("downloadPopup", t('SettingsEnableDownloadPopup'), 1, t('AccessibilityEnableDownloadPopup')) : ''}`
}) + settingsCategory({
name: "accessibility",
title: t('SettingsAccessibilitySubtitle'),
body: dropdownSelect(t('SettingsAccessibilityLanguage'), 'language', languagePickerNames)
})
}],
})}

View File

@ -84,11 +84,24 @@ export function cleanURL(url, host) {
}
return url.slice(0, 128)
}
export function getCookie(req, id) {
if(!req.headers.cookie) return undefined;
let cookies = {};
for(let i of req.headers.cookie.split(';')) {
const [key, value] = i.trim().split('=');
cookies[key] = value;
}
return cookies[id]
}
export function verifyLanguageCode(code) {
return RegExp(/[a-z]{2}/).test(String(code.slice(0, 2).toLowerCase())) ? String(code.slice(0, 2).toLowerCase()) : "en"
}
export function languageCode(req) {
return req.header('Accept-Language') ? verifyLanguageCode(req.header('Accept-Language')) : "en"
const overrideLanguage = getCookie(req, 'language');
let language;
if(overrideLanguage) language = overrideLanguage
else language = req.header('Accept-Language');
return language ? verifyLanguageCode(language) : 'en';
}
export function unicodeDecode(str) {
return str.replace(/\\u[\dA-F]{4}/gi, (unicode) => {