-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lazy-loading translations #7
Comments
Great idea! I definitely think that lazy-loading strings on a per-feature basis should be encouraged. Currently it is actually possible to lazy-load strings, you can see an example on how you can achieve it here. lit-translate/src/demo/pages/demo-page.ts Lines 42 to 55 in 7db7188
I think it would be a great addition if lit-translate could export a function to allow for easy lazy-loading. I will take a look at it in the near future 😊 |
Is there a sync API for this as well? In the example above, we work assuming that the entire component module is synchronously loaded, which helps avoid FOUC. I think both APIs would be useful, one which registers strings synchronously when the module is loaded, and one which loads strings async at runtime |
Here is a tentative approach to load locale resources per component (litElement) and not globally for the application. It is a bit hacky as it injects new objects into What would be nice as an ~enhancement is a cleaner path to achieve the same thing ; ) The mixin below allows: import { LitElement, html, css } from 'lit-element';
import locale from './myLocale.js';
/*
// Note(cg): myLocal.js example
export default {
completed: {
online: {
title: 'Submit the form',
info: 'Once submitted, <strong>this form can’t be changed</strong>. Please review the information you have provided before submitting.'
}
};
*/
import Translate from '../../util/translate-mixin.js';
class PapFormSectionSubmit extends Translate(LitElement, locale) {
render() {
// this.translate will add component name to the translation key
return html `
<h2>${this.translate('completed.online.title')}</h2>
<p>${this.translateUnsageHTML('completed.online.info')}</p>`;
}
}
// Register the new element with the browser.
customElements.define('pap-form-section-submit', PapFormSectionSubmit); Mixin (connect stuff connects language to a redux store with https://github.com/albertopumar/lit-element-redux): import connect from './connect-store.js';
import { registerTranslateConfig, use, translate, translateUnsafeHTML } from 'lit-translate';
const LANG = 'en';
const mapStateToProps = state => {
return {
language: state.language,
};
};
const mapDispatchToProps = dispatch => {
return {
set_language: ([lan]) => dispatch({ type: 'SET_LANGUAGE', language: lan }),
};
};
let translateConfig;
registerTranslateConfig({
// Note(cg): loader is injecting component-keyed additional objects
loader: async (lang, config) => {
translateConfig = config;
// loading per component
const strings = config.strings || {};
config.strings = strings;
config.loaders = config.loaders || {};
config.needLoading = config.needLoading || {};
config.currentLang = config.currentLang || {};
return Promise.all(Object.keys(config.needLoading).map(async key => strings[key] = await config.loaders[key](lang, config)))
.then(() => {
return strings;
});
}
});
// Note(cg): we need to call use early as we need to inject `loaders`, `needLoading` ...
use(LANG);
/**
* mixin enabling component-based translation
* @param {Class} baseElement base class
* @param {Object} locale JSON object containing text for initial/defauld language
* @return {Class} extended class
*/
const EnableTranslation = (baseElement, locale) => {
const cls = class extends baseElement {
static get properties() {
return {
...super.properties,
language: { type: String }
};
}
static get locale() {
return locale;
}
constructor() {
super();
// Note(cg): adding loader first time the class instantiated. .
if (!translateConfig.strings[this.constructor.name]) {
translateConfig.currentLang[this.constructor.name] = LANG;
translateConfig.strings[this.constructor.name] = locale;
translateConfig.loaders[this.constructor.name] = this.translationLoader();
}
}
translationLoader() {
const name = this.constructor.name;
return async (lang, config) => {
if (lang === LANG) {
return locale;
}
// Note(cg): load localized resource on firebase.
return await firebase.database().ref(`/appSettingsLocale/component/${name}/${lang}`).once('value')
.then(snap => {
delete translateConfig.needLoading[name];
return snap.val();
});
};
}
updated(props) {
if (props.has('language')) {
const lang = translateConfig.currentLang[this.constructor.name];
translateConfig.currentLang[this.constructor.name] = this.language;
if (lang !== this.language) {
translateConfig.needLoading[this.constructor.name] = true;
}
use(this.language);
}
super.updated();
}
translate(key) {
return translate(`${this.constructor.name}.${key}`);
}
translateUnsafeHTML(key) {
return translateUnsafeHTML(`${this.constructor.name}.${key}`);
}
};
return connect(mapStateToProps, mapDispatchToProps)(cls);
};
export default EnableTranslation; |
I'd like to lazy-load strings on a per-feature basis, like
Currently, it looks from the docs that strings have to be loaded statically as a monolith, either that or deep internals of lit-translate have to be modified. It would be great if I could do something like this:
The text was updated successfully, but these errors were encountered: