remove bloat fonts, get rid of svelte-i18n
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
@@ -1,67 +1,225 @@
|
||||
import { init, locale, register, waitLocale } from "svelte-i18n";
|
||||
import { derived, get, writable } from "svelte/store";
|
||||
import { browser } from "$app/environment";
|
||||
import { get, writable } from "svelte/store";
|
||||
import yaml from "js-yaml";
|
||||
|
||||
const locale_default = "en";
|
||||
let locale_index = writable(0);
|
||||
let locale_list = [];
|
||||
// defines a single locale
|
||||
class Locale {
|
||||
constructor(code, icon) {
|
||||
// regex for "render"ing the locale
|
||||
this.ref_regex = /\[[0-9]*:.*?\]/gm;
|
||||
this.link_regex = /\[[^\]]*]\([^ ]*\)/gm;
|
||||
this.bold_regex = /\*\*.*?\*\*/gm;
|
||||
|
||||
function locale_setup() {
|
||||
// english
|
||||
register("en", () => import("../locales/en.json"));
|
||||
locale_list.push({ code: "en", name: "English", icon: "🇬🇧" });
|
||||
|
||||
// turkish
|
||||
register("tr", () => import("../locales/tr.json"));
|
||||
locale_list.push({ code: "tr", name: "Turkish", icon: "🇹🇷" });
|
||||
|
||||
init({
|
||||
fallbackLocale: locale_default,
|
||||
initialLocale: get(locale),
|
||||
});
|
||||
}
|
||||
|
||||
function locale_from_browser() {
|
||||
if (browser) return window.navigator.language.slice(0, 2).toLowerCase();
|
||||
else return locale_default;
|
||||
}
|
||||
|
||||
function locale_select(l = null) {
|
||||
if (l === null) {
|
||||
if (browser && null !== (l = localStorage.getItem("locale")))
|
||||
locale_select(l);
|
||||
else locale_select(locale_from_browser());
|
||||
return;
|
||||
this.code = code; // BCP 47 language tag
|
||||
this.icon = icon; // icon for the locale
|
||||
this.all = {}; // all the locales
|
||||
}
|
||||
|
||||
l = l.slice(0, 2);
|
||||
|
||||
for (let i = 0; i < locale_list.length; i++) {
|
||||
if (l !== locale_list[i].code) continue;
|
||||
|
||||
if (browser) localStorage.setItem("locale", l);
|
||||
|
||||
locale.set(l);
|
||||
locale_index.set(i);
|
||||
|
||||
return;
|
||||
// load the locale
|
||||
async load() {
|
||||
const text = await import(`../locales/${this.code}.yaml?raw`);
|
||||
this.all = yaml.load(text.default);
|
||||
}
|
||||
|
||||
locale.set(locale_default);
|
||||
locale_index.set(0);
|
||||
// renders a given locale using given values and links
|
||||
render(locale, values, links) {
|
||||
// get rid of newlines and remove trailing/repeating spaces and stuff
|
||||
locale = locale.replaceAll("\r", "").replaceAll("\n", " ");
|
||||
locale = locale.trim();
|
||||
|
||||
// find and replace all the values
|
||||
for (let name in values) {
|
||||
// values cannot be objects
|
||||
if (typeof values[name] === "object") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// "{name}" will be replaced by the values
|
||||
locale = locale.replaceAll(`{${name}}`, values[name]);
|
||||
}
|
||||
|
||||
// find all the references
|
||||
const refs = [...locale.matchAll(this.ref_regex)];
|
||||
|
||||
// and repalce them
|
||||
for (let i = 0; i < refs.length; i++) {
|
||||
let ref = refs[i][0];
|
||||
let name = ref.replaceAll(/(^\[|\]$)/g, "");
|
||||
let indx = parseInt(name.charAt(0)) - 1;
|
||||
name = name.substring(2);
|
||||
|
||||
// check the index
|
||||
if (indx >= links.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// replace the reference with a link
|
||||
locale = locale.replaceAll(ref, `<a href="${links[indx]}">${name}</a>`);
|
||||
}
|
||||
|
||||
// look for []() patterns, which are used adding links, kinda like markdown
|
||||
// but this is shittier
|
||||
links = [...locale.matchAll(this.link_regex)];
|
||||
|
||||
// replace the found links
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
let link = links[i][0];
|
||||
let name = link.match(/(?<=\[).*?(?=])/g);
|
||||
let url = link.match(/(?<=\()[^ ]*(?=\))/g);
|
||||
|
||||
// if we fail to extract the link name and/or URL, skip this match
|
||||
if (null === name || null === url) continue;
|
||||
|
||||
locale = locale.replaceAll(link, `<a href="${url[0]}">${name[0]}</a>`);
|
||||
}
|
||||
|
||||
// look for double stars which is used for bold text
|
||||
const bolds = [...locale.matchAll(this.bold_regex)];
|
||||
|
||||
// replace bold text with actual bold text
|
||||
for (let i = 0; i < bolds.length; i++) {
|
||||
let bold = bolds[i][0];
|
||||
let text = bold.match(/(?<=\*\*).*?(?=\*\*)/g);
|
||||
|
||||
// if we fail to extract the text content, skip this match
|
||||
if (null === text) continue;
|
||||
|
||||
locale = locale.replaceAll(bold, `<b>${text}</b>`);
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
// resolve the given locale
|
||||
resolve(key, vars = {}) {
|
||||
let cur = this.all;
|
||||
let keys = key.split(".");
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
cur = cur[keys[i]];
|
||||
|
||||
if (cur === undefined) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
// locale needs to be a string
|
||||
if (typeof cur !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// extract links from the vars
|
||||
let links = vars.links;
|
||||
delete vars.links;
|
||||
|
||||
return this.render(cur, vars, links);
|
||||
}
|
||||
}
|
||||
|
||||
async function locale_wait() {
|
||||
await waitLocale();
|
||||
// localizer stores and defines all the locales
|
||||
class Localizer {
|
||||
constructor() {
|
||||
// list of supported locales
|
||||
this.list = [
|
||||
new Locale("en", "🇬🇧"), // English
|
||||
new Locale("tr", "🇹🇷"), // Turkish
|
||||
];
|
||||
|
||||
this.current = writable(this.list[0]); // current locale
|
||||
this.next = writable(this.list[1]); // next locale
|
||||
this.fallback = this.list[0]; // fallback locale
|
||||
}
|
||||
|
||||
// get the name of a language using the current locale
|
||||
name(code) {
|
||||
return get(this.current).name(code);
|
||||
}
|
||||
|
||||
// get the current browser locale tag
|
||||
browser() {
|
||||
if (browser) {
|
||||
window.navigator.language.slice(0, 2).toLowerCase();
|
||||
} else {
|
||||
return this.fallback.code;
|
||||
}
|
||||
}
|
||||
|
||||
/* load all the locales, attempt to set the provided locale as the current
|
||||
* locale, if the provided locale is not available just use the default */
|
||||
async setup(code) {
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
await this.list[i].load();
|
||||
}
|
||||
|
||||
// find the locale index by it's code
|
||||
let indx = this.list.findIndex(locale => {
|
||||
return locale.code === code;
|
||||
});
|
||||
|
||||
// check the index to see if we found the locale
|
||||
if (indx < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we actually found it, set it as the current locale
|
||||
this.current.set(this.list[indx]);
|
||||
|
||||
// set the next locale
|
||||
if (++indx >= this.list.length) {
|
||||
this.next.set(this.list[0]);
|
||||
} else {
|
||||
this.next.set(this.list[indx]);
|
||||
}
|
||||
}
|
||||
|
||||
// switch to the next locale
|
||||
switch() {
|
||||
// find the next locale's index
|
||||
let indx = this.list.findIndex(locale => {
|
||||
return locale === get(this.next);
|
||||
});
|
||||
|
||||
// set next locale as the new current locale
|
||||
this.current.set(get(this.next));
|
||||
document.cookie = `locale=${get(this.next).code}`;
|
||||
|
||||
// get the next locale based on the index
|
||||
if (indx === this.list.length - 1) {
|
||||
this.next.set(this.list[(indx = 0)]);
|
||||
} else {
|
||||
this.next.set(this.list[++indx]);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(key, vars = {}) {
|
||||
// attempt to resolve the given key
|
||||
let res = get(this.current).resolve(key, vars);
|
||||
|
||||
if (res !== undefined) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// if we fail to resolve the key, try to resolve it using the fallback
|
||||
// locale, if that fails too then we are kinda fucked so yeah we just throw
|
||||
// an error
|
||||
if (get(this.current) === this.fallback) {
|
||||
throw new Error(`missing key: ${key}`);
|
||||
} else {
|
||||
return this.fallback.resolve(key, vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
export const localizer = new Localizer(); // global localizer
|
||||
export const locale = localizer.current; // current locale
|
||||
export const next = localizer.next; // next locale
|
||||
|
||||
// resolve a given locale by it's key
|
||||
export const _ = derived(
|
||||
locale,
|
||||
locale_list,
|
||||
locale_index,
|
||||
locale_default,
|
||||
locale_setup,
|
||||
locale_wait,
|
||||
locale_select,
|
||||
locale_from_browser,
|
||||
};
|
||||
() =>
|
||||
(key, vars = {}) =>
|
||||
localizer.resolve(key, vars)
|
||||
);
|
||||
|
||||
export default localizer;
|
||||
|
Reference in New Issue
Block a user