mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-16 10:18:28 +00:00
add language picker
This commit is contained in:
parent
cf6dcfe7a6
commit
1ff5940375
@ -862,4 +862,37 @@ input[type="checkbox"] {
|
|||||||
height: 6rem;
|
height: 6rem;
|
||||||
width: 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;
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ let checkboxes = ["disableTikTokWatermark", "fullTikTokAudio", "muteAudio"];
|
|||||||
let exceptions = { // used for mobile devices
|
let exceptions = { // used for mobile devices
|
||||||
"vQuality": "720"
|
"vQuality": "720"
|
||||||
}
|
}
|
||||||
|
let dropdowns = ["language"]
|
||||||
|
|
||||||
function eid(id) {
|
function eid(id) {
|
||||||
return document.getElementById(id)
|
return document.getElementById(id)
|
||||||
@ -30,6 +31,19 @@ function sGet(id) {
|
|||||||
function sSet(id, value) {
|
function sSet(id, value) {
|
||||||
localStorage.setItem(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) {
|
function enable(id) {
|
||||||
eid(id).dataset.enabled = "true";
|
eid(id).dataset.enabled = "true";
|
||||||
}
|
}
|
||||||
@ -248,6 +262,15 @@ function checkbox(action) {
|
|||||||
}
|
}
|
||||||
action === "disableChangelog" && sGet(action) === "true" ? notificationCheck("disable") : notificationCheck();
|
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() {
|
function loadSettings() {
|
||||||
try {
|
try {
|
||||||
if (typeof(navigator.clipboard.readText) == "undefined") throw new Error();
|
if (typeof(navigator.clipboard.readText) == "undefined") throw new Error();
|
||||||
@ -268,6 +291,13 @@ function loadSettings() {
|
|||||||
for (let i in switchers) {
|
for (let i in switchers) {
|
||||||
changeSwitcher(i, sGet(i))
|
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) {
|
function changeButton(type, text) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -443,4 +473,4 @@ eid("url-input-area").addEventListener("keyup", (event) => {
|
|||||||
document.onkeydown = (event) => {
|
document.onkeydown = (event) => {
|
||||||
if (event.key === "Tab" || event.ctrlKey) eid("url-input-area").focus();
|
if (event.key === "Tab" || event.ctrlKey) eid("url-input-area").focus();
|
||||||
if (event.key === 'Escape') hideAllPopups();
|
if (event.key === 'Escape') hideAllPopups();
|
||||||
}
|
}
|
@ -117,6 +117,8 @@
|
|||||||
"SettingsDubDefault": "original",
|
"SettingsDubDefault": "original",
|
||||||
"SettingsDubAuto": "auto",
|
"SettingsDubAuto": "auto",
|
||||||
"SettingsVimeoPrefer": "vimeo downloads type",
|
"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:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ const locPath = './src/localization/languages'
|
|||||||
|
|
||||||
let loc = {}
|
let loc = {}
|
||||||
let languages = [];
|
let languages = [];
|
||||||
|
let languageNames = [];
|
||||||
|
|
||||||
export function loadLoc() {
|
export function loadLoc() {
|
||||||
fs.readdir(locPath, (err, files) => {
|
fs.readdir(locPath, (err, files) => {
|
||||||
@ -13,6 +14,7 @@ export function loadLoc() {
|
|||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
loc[file.split('.')[0]] = loadJson(`${locPath}/${file}`);
|
loc[file.split('.')[0]] = loadJson(`${locPath}/${file}`);
|
||||||
languages.push(file.split('.')[0])
|
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 languageList = languages;
|
||||||
|
export const languagePickerNames = languageNames;
|
@ -173,3 +173,16 @@ export function celebrationsEmoji() {
|
|||||||
let dm = `${n[1]}-${n[2]}`;
|
let dm = `${n[1]}-${n[2]}`;
|
||||||
return Object.keys(celebrations).includes(dm) ? celebrations[dm] : "🐲";
|
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;
|
||||||
|
}
|
@ -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 { services as s, appName, authorInfo, version, repo, donations, supportedAudio } from "../config.js";
|
||||||
import { getCommitInfo } from "../sub/currentCommit.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 emoji from "../emoji.js";
|
||||||
import changelogManager from "../changelog/changelogManager.js";
|
import changelogManager from "../changelog/changelogManager.js";
|
||||||
|
|
||||||
@ -319,6 +319,10 @@ export default function(obj) {
|
|||||||
name: "miscellaneous",
|
name: "miscellaneous",
|
||||||
title: t('Miscellaneous'),
|
title: t('Miscellaneous'),
|
||||||
body: checkbox("disableChangelog", t('SettingsDisableNotifications')) + `${!isIOS ? checkbox("downloadPopup", t('SettingsEnableDownloadPopup'), 1, t('AccessibilityEnableDownloadPopup')) : ''}`
|
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)
|
||||||
})
|
})
|
||||||
}],
|
}],
|
||||||
})}
|
})}
|
||||||
|
@ -84,11 +84,24 @@ export function cleanURL(url, host) {
|
|||||||
}
|
}
|
||||||
return url.slice(0, 128)
|
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) {
|
export function verifyLanguageCode(code) {
|
||||||
return RegExp(/[a-z]{2}/).test(String(code.slice(0, 2).toLowerCase())) ? String(code.slice(0, 2).toLowerCase()) : "en"
|
return RegExp(/[a-z]{2}/).test(String(code.slice(0, 2).toLowerCase())) ? String(code.slice(0, 2).toLowerCase()) : "en"
|
||||||
}
|
}
|
||||||
export function languageCode(req) {
|
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) {
|
export function unicodeDecode(str) {
|
||||||
return str.replace(/\\u[\dA-F]{4}/gi, (unicode) => {
|
return str.replace(/\\u[\dA-F]{4}/gi, (unicode) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user