Reputation: 43
I have a static class for localising the data on my site, and I want to be able to load the required files, rather than all of them. It was fine for testing, but in production, each page that requires translation loads ~7MB of bundled lang files, despite only using one.
I have a single page on the site to change the language, and that page does not translation, so there is no occasion where a user needs the see the language visibly change on the same page.
These language files are not created by me and therefore I cannot reduce their sizes, how could I make it so that just the correct file is served
Using svelte-kit, rollup, vite
import cn from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_cn.csv';
import de from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_de.csv';
import en from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv';
import fr from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_fr.csv';
import id from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_id.csv';
import jp from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_JP.csv';
import kr from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_kor.csv';
import pt from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_pt.csv';
import ru from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_ru.csv';
import sp from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_sp.csv';
import tc from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_tc.csv';
import th from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_th.csv';
import vn from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_vn.csv';
const bindings = {
cn: cn,
de: de,
en: en,
fr: fr,
id: id,
jp: jp,
kr: kr,
pt: pt,
ru: ru,
sp: sp,
tc: tc,
th: th,
vn: vn
};
class Lang {
// eslint-disable-next-line no-unused-vars
static Get(str, remove_spaces = false, must_translate = false) {
if (remove_spaces) {
str = str.replace(/ /g, '_').toUpperCase();
}
try {
const entry = bindings[Cookies.get('lang')].find((entry) => entry.name === str);
let composedregex = new RegExp('<[^>]*>', 'g');
return entry.value.replaceAll(composedregex, '');
} catch (e) {
if (must_translate) {
return null;
} else {
try {
// Fallback to English
const entry = en.find((entry) => entry.name === str);
let composedregex = new RegExp('<[^>]*>', 'g');
const ret = entry.value.replaceAll(composedregex, '');
return ret;
} catch (error) {
// Total failure -> return original string
return str;
}
}
}
}
}
export default Lang;
Upvotes: 1
Views: 378
Reputation: 1074385
Caveat: I don't use SvelteKit. (Nothing against it or Svelte, I just don't use them, at least not yet.)
But the usual solution here is to use dynamic import()
, like this (see ***
comments):
// *** Since we always use `en`, import it statically
import en from "../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv";
// *** Why are the filenames not consistently aligned with the `lang` values?
// This map is unnecessary if the files are renamed (or the `lang` is updated
// to match them).
const langToFilenameFragment = {
"jp": "JP",
"kr": "kor",
};
// *** Import the cookie-defined language dynamically
const lang = Cookies.get("lang");
const fragment = langToFilenameFragment[lang] ?? lang; // *** Again, could avoid thsi
const bindings = {
en,
[lang]: await import(`../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_${fragment}.csv`),
};
class Lang {
// eslint-disable-next-line no-unused-vars
static Get(str, remove_spaces = false, must_translate = false) {
if (remove_spaces) {
str = str.replace(/ /g, "_").toUpperCase();
}
try {
const entry = bindings[lang].find((entry) => entry.name === str); // *** Used `lang` here
let composedregex = new RegExp("<[^>]*>", "g");
return entry.value.replaceAll(composedregex, "");
} catch (e) {
if (must_translate) {
return null;
} else {
try {
// Fallback to English
const entry = en.find((entry) => entry.name === str);
let composedregex = new RegExp("<[^>]*>", "g");
const ret = entry.value.replaceAll(composedregex, "");
return ret;
} catch (error) {
// Total failure -> return original string
return str;
}
}
}
}
}
export default Lang;
If, like some bundlers, Svelte Kit doesn't like dynamic import()
with a truly dynamic (rather than hardcoded) paths, you can get around that with a switch
:
// *** Since we always use `en`, import it statically
import en from "../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv";
// *** Import the cookie-defined language dynamically
const lang = Cookies.get("lang");
const translation = await ((() => {
switch (lang) {
case "cn": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_cn.csv");
case "de": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_de.csv");
case "en": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv");
case "fr": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_fr.csv");
case "id": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_id.csv");
case "jp": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_JP.csv");
case "kr": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_kor.csv");
case "pt": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_pt.csv");
case "ru": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_ru.csv");
case "sp": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_sp.csv");
case "tc": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_tc.csv");
case "th": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_th.csv");
case "vn": return import("../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_vn.csv");
default: throw new Error(`Invalid 'lang' cookie "${lang}"`);
}
})()).default;
const bindings = {
en,
[lang]: translation,
};
class Lang {
// eslint-disable-next-line no-unused-vars
static Get(str, remove_spaces = false, must_translate = false) {
if (remove_spaces) {
str = str.replace(/ /g, "_").toUpperCase();
}
try {
const entry = bindings[lang].find((entry) => entry.name === str); // *** Used `lang` here
let composedregex = new RegExp("<[^>]*>", "g");
return entry.value.replaceAll(composedregex, "");
} catch (e) {
if (must_translate) {
return null;
} else {
try {
// Fallback to English
const entry = en.find((entry) => entry.name === str);
let composedregex = new RegExp("<[^>]*>", "g");
const ret = entry.value.replaceAll(composedregex, "");
return ret;
} catch (error) {
// Total failure -> return original string
return str;
}
}
}
}
}
export default Lang;
You may need a custom setting (sometimes it's a comment, like Webpack's webpackChunkName
) telling SvelteKit to make each of those dynamically-imported modules its own bundle.
Upvotes: 1