lion/packages/localize/src/LocalizeMixin.js
Joren Broekema 09d9675963 feat(localize): add types to localize
Co-authored-by: narzac <narzac@gmail.com>
2020-08-03 17:00:26 +02:00

155 lines
4 KiB
JavaScript

import { dedupeMixin, until, nothing } from '@lion/core';
import { localize } from './localize.js';
/**
* @typedef {import('../types/LocalizeMixinTypes').LocalizeMixin} LocalizeMixin
*/
/**
* # LocalizeMixin - for self managed templates
* @type {LocalizeMixin}
*/
const LocalizeMixinImplementation = superclass =>
// eslint-disable-next-line
class LocalizeMixin extends superclass {
/**
* @returns {Object.<string,function>[]}
*/
static get localizeNamespaces() {
return [];
}
/**
* @returns {boolean}
*/
static get waitForLocalizeNamespaces() {
return true;
}
constructor() {
super();
this.__boundLocalizeOnLocaleChanged =
/** @param {...Object} args */
(...args) => {
const event = /** @type {CustomEvent} */ (Array.from(args)[0]);
this.__localizeOnLocaleChanged(event);
};
// should be loaded in advance
this.__localizeStartLoadingNamespaces();
if (this.localizeNamespacesLoaded) {
this.localizeNamespacesLoaded.then(() => {
this.__localizeMessageSync = true;
});
}
}
/**
* hook into LitElement to only render once all translations are loaded
* @returns {Promise.<void>}
*/
async performUpdate() {
if (Object.getPrototypeOf(this).constructor.waitForLocalizeNamespaces) {
await this.localizeNamespacesLoaded;
}
super.performUpdate();
}
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
if (this.localizeNamespacesLoaded) {
this.localizeNamespacesLoaded.then(() => this.onLocaleReady());
}
this.__localizeAddLocaleChangedListener();
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
this.__localizeRemoveLocaleChangedListener();
}
/**
* @param {string | string[]} keys
* @param {Object.<string,?>} variables
* @param {Object} [options]
* @param {string} [options.locale]
* @return {string | function}
*/
msgLit(keys, variables, options) {
if (this.__localizeMessageSync) {
return localize.msg(keys, variables, options);
}
if (!this.localizeNamespacesLoaded) {
return '';
}
return until(
this.localizeNamespacesLoaded.then(() => localize.msg(keys, variables, options)),
nothing,
);
}
/**
* @returns {string[]}
*/
__getUniqueNamespaces() {
/** @type {string[]} */
const uniqueNamespaces = [];
// IE11 does not support iterable in the constructor
const s = new Set();
Object.getPrototypeOf(this).constructor.localizeNamespaces.forEach(s.add.bind(s));
s.forEach(uniqueNamespace => {
uniqueNamespaces.push(uniqueNamespace);
});
return uniqueNamespaces;
}
__localizeStartLoadingNamespaces() {
this.localizeNamespacesLoaded = localize.loadNamespaces(this.__getUniqueNamespaces());
}
__localizeAddLocaleChangedListener() {
localize.addEventListener('localeChanged', this.__boundLocalizeOnLocaleChanged);
}
__localizeRemoveLocaleChangedListener() {
localize.removeEventListener('localeChanged', this.__boundLocalizeOnLocaleChanged);
}
/**
* @param {CustomEvent} event
*/
__localizeOnLocaleChanged(event) {
this.onLocaleChanged(event.detail.newLocale, event.detail.oldLocale);
}
onLocaleReady() {
this.onLocaleUpdated();
}
/**
* @param {string} newLocale
* @param {string} oldLocale
*/
// eslint-disable-next-line no-unused-vars
onLocaleChanged(newLocale, oldLocale) {
this.__localizeStartLoadingNamespaces();
this.onLocaleUpdated();
this.requestUpdate();
}
// eslint-disable-next-line class-methods-use-this
onLocaleUpdated() {}
};
export const LocalizeMixin = dedupeMixin(LocalizeMixinImplementation);