• Added language support

• Added timezone support
This commit is contained in:
nutty
2026-08-29 12:11:04 +10:00
parent 121c351416
commit acc187d072
3 changed files with 128 additions and 20 deletions
+43 -1
View File
@@ -188,6 +188,21 @@ function LoadJSON(settingsJson) {
await PopulateFontDatalist(); await PopulateFontDatalist();
}, { once: true }); }, { once: true });
break; break;
case 'timezone':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.placeholder = 'Type to search timezone...';
inputElement.id = setting.id;
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
inputElement.setAttribute('list', 'timezones');
inputElement.autocomplete = 'off';
// Populate datalist on focus (runs once)
inputElement.addEventListener('focus', function loadOnce() {
inputElement.removeEventListener('focus', loadOnce);
PopulateTimezoneDatalist();
}, { once: true });
break;
case 'button': case 'button':
inputElement = document.createElement('button'); inputElement = document.createElement('button');
inputElement.id = setting.id; //Added setting ID inputElement.id = setting.id; //Added setting ID
@@ -431,6 +446,30 @@ async function PopulateFontDatalist() {
} }
} }
function PopulateTimezoneDatalist() {
try {
// Fetch all official IANA timezones natively from the browser
const timezones = Intl.supportedValuesOf('timeZone');
// Create the datalist element
const datalistElement = document.createElement('datalist');
datalistElement.id = 'timezones';
// Append each timezone as an option
timezones.forEach(tz => {
const option = document.createElement('option');
option.value = tz;
datalistElement.appendChild(option);
});
document.body.appendChild(datalistElement);
console.debug(`Loaded ${timezones.length} timezones into auto-suggest.`);
} catch (err) {
console.error("Error generating timezone suggestions:", err);
}
}
///////////////////////// /////////////////////////
@@ -599,4 +638,7 @@ LoadSettingsFromStorage();
LoadJSON(settingsJson); LoadJSON(settingsJson);
// Populate local fonts for auto-suggest // Populate local fonts for auto-suggest
PopulateFontDatalist(); PopulateFontDatalist();
// Populate timezones for auto-suggest
PopulateTimezoneDatalist();
+36 -19
View File
@@ -27,6 +27,8 @@ const line3 = document.getElementById('line3');
///////////// /////////////
const font = urlParams.get("font") || ""; const font = urlParams.get("font") || "";
const language = urlParams.get("language") || "en";
const timezone = urlParams.get("timezone") || "";
const enableLine1 = GetBooleanParam("enableLine1", true); const enableLine1 = GetBooleanParam("enableLine1", true);
const line1Format = urlParams.get("line1Format") || "hh:mm:ss A"; const line1Format = urlParams.get("line1Format") || "hh:mm:ss A";
@@ -63,7 +65,7 @@ const line3TextAlignment = urlParams.get("line3TextAlignment") || "center";
// Set the font for the entire page if specified // Set the font for the entire page if specified
if (font) if (font)
document.body.style.fontFamily = `'${font}'`; document.body.style.fontFamily = `'${font}'`;
// Hide lines that are not enabled // Hide lines that are not enabled
if (!enableLine1) if (!enableLine1)
@@ -75,38 +77,53 @@ if (!enableLine3)
//////////// ////////////////
// CLOCKO // // CLOCKO //
//////////// ////////////////
// Check if any active format string includes milliseconds (e.g., 'S', 'SS', 'SSS') // Helper function to start the clock loop
const usesMilliseconds = function StartClock() {
(enableLine1 && line1Format.includes('S')) || // Check if any active format string includes milliseconds (e.g., 'S', 'SS', 'SSS')
(enableLine2 && line2Format.includes('S')) || const usesMilliseconds =
(enableLine3 && line3Format.includes('S')); (enableLine1 && line1Format.includes('S')) ||
(enableLine2 && line2Format.includes('S')) ||
(enableLine3 && line3Format.includes('S'));
UpdateTime(); UpdateTime();
if (usesMilliseconds) { if (usesMilliseconds) {
// High-frequency updates for millisecond precision function updateFrame() {
function updateFrame() { UpdateTime();
UpdateTime(); requestAnimationFrame(updateFrame);
}
requestAnimationFrame(updateFrame); requestAnimationFrame(updateFrame);
} else {
setInterval(UpdateTime, 1000);
} }
requestAnimationFrame(updateFrame);
} else {
// Efficient 1-second interval for standard clocks
setInterval(UpdateTime, 1000);
} }
function UpdateTime() { function UpdateTime() {
const now = dayjs().tz(dayjs.tz.guess()); const activeTimezone = timezone ? timezone : dayjs.tz.guess();
const now = dayjs().tz(activeTimezone);
if (enableLine1) line1.textContent = now.format(line1Format); if (enableLine1) line1.textContent = now.format(line1Format);
if (enableLine2) line2.textContent = now.format(line2Format); if (enableLine2) line2.textContent = now.format(line2Format);
if (enableLine3) line3.textContent = now.format(line3Format); if (enableLine3) line3.textContent = now.format(line3Format);
} }
// Set the language and start the clock only after it's loaded
const script = document.createElement('script');
script.src = `https://cdn.jsdelivr.net/npm/dayjs@1/locale/${language}.js`;
script.onload = () => {
dayjs.locale(language);
StartClock();
};
script.onerror = () => {
console.warn(`Locale '${language}' failed to load. Falling back to English.`);
dayjs.locale('en');
StartClock();
};
document.head.appendChild(script);
///////////// /////////////
+49
View File
@@ -1,5 +1,54 @@
{ {
"settings": [ "settings": [
{
"id": "language",
"label": "Language",
"description": "",
"type": "select",
"options": [
{ "value": "en", "label": "English" },
{ "value": "ar", "label": "العربية (Arabic)" },
{ "value": "bg", "label": "Български (Bulgarian)" },
{ "value": "zh-cn", "label": "中文 (Chinese Simplified)" },
{ "value": "zh-tw", "label": "中文 (Chinese Traditional)" },
{ "value": "cs", "label": "Čeština (Czech)" },
{ "value": "da", "label": "Dansk (Danish)" },
{ "value": "nl", "label": "Nederlands (Dutch)" },
{ "value": "fi", "label": "Suomi (Finnish)" },
{ "value": "fr", "label": "Français (French)" },
{ "value": "de", "label": "Deutsch (German)" },
{ "value": "el", "label": "Ελληνικά (Greek)" },
{ "value": "he", "label": "עברית (Hebrew)" },
{ "value": "hi", "label": "हिन्दी (Hindi)" },
{ "value": "hu", "label": "Magyar (Hungarian)" },
{ "value": "id", "label": "Bahasa Indonesia (Indonesian)" },
{ "value": "it", "label": "Italiano (Italian)" },
{ "value": "ja", "label": "日本語 (Japanese)" },
{ "value": "ko", "label": "한국어 (Korean)" },
{ "value": "nb", "label": "Norsk bokmål (Norwegian Bokmål)" },
{ "value": "pl", "label": "Polski (Polish)" },
{ "value": "pt", "label": "Português (Portuguese)" },
{ "value": "ro", "label": "Română (Romanian)" },
{ "value": "ru", "label": "Русский (Russian)" },
{ "value": "sk", "label": "Slovenčina (Slovak)" },
{ "value": "es", "label": "Español (Spanish)" },
{ "value": "sv", "label": "Svenska (Swedish)" },
{ "value": "th", "label": "ไทย (Thai)" },
{ "value": "tr", "label": "Türkçe (Turkish)" },
{ "value": "uk", "label": "Українська (Ukrainian)" },
{ "value": "vi", "label": "Tiếng Việt (Vietnamese)" }
],
"defaultValue": "en",
"group": "General"
},
{
"id": "timezone",
"label": "Timezone",
"description": "Enter an IANA timezone (e.g., America/New_York, Europe/London). Leave blank to use local time.",
"type": "timezone",
"defaultValue": "",
"group": "General"
},
{ {
"id": "font", "id": "font",
"label": "Font", "label": "Font",