wuchale
Version:
Protobuf-like i18n from plain code
60 lines (59 loc) • 1.86 kB
JavaScript
export const catalogVarName = 'c';
let onInvalidFunc = () => '';
// @ts-expect-error
if (import.meta.env?.DEV) {
onInvalidFunc = (i, c) => {
const item = c[i];
if (item == null) {
return `[i18n-404:${i}]`;
}
return `[i18n-400:${i}(${item})]`;
};
}
export function onInvalid(newOnInvalid) {
onInvalidFunc = newOnInvalid;
}
/** get translation using composite context */
function mixedToString(ctx, args = [], start = 1) {
let msgStr = '';
for (let i = start; i < ctx.length; i++) {
const fragment = ctx[i];
if (typeof fragment === 'string') {
msgStr += fragment;
}
else { // index of non-text children
msgStr += args[fragment];
}
}
return msgStr;
}
// Can't make it a class because reactivity is lost on svelte and possibly others too
export default function toRuntime(mod = { [catalogVarName]: [] }, locale) {
const catalog = mod[catalogVarName];
/** get composite context */
const getCompositeContext = (id) => {
const ctx = catalog[id];
if (typeof ctx == 'string') {
return [ctx];
}
if (Array.isArray(ctx)) {
return ctx;
}
return [onInvalidFunc(id, catalog)];
};
return {
_: mod,
l: locale,
cx: getCompositeContext,
tx: mixedToString,
/** for tagged template strings */
tt: (tag, id, args) => {
const ctx = getCompositeContext(id);
return tag(ctx.filter(m => typeof m === 'string'), ...ctx.filter(m => typeof m === 'number').map(a => args?.[a]));
},
/** get translation for plural */
tp: (id) => catalog[id] ?? [],
/** get translation */
t: (id, args = []) => mixedToString(getCompositeContext(id), args, 0)
};
}