Skip to content

Commit

Permalink
feat: reintroduced the langChanged directive
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasbm committed Apr 22, 2022
1 parent a4913b9 commit 2703f1b
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 114 deletions.
124 changes: 62 additions & 62 deletions src/demo/pages/demo-page.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, eventOptions, property } from "lit/decorators.js";
import { repeat } from "lit/directives/repeat.js";
import { get, LanguageIdentifier, registerTranslateConfig, translate, translateUnsafeHTML, use } from "../../lib";
import {html, LitElement, PropertyValues, TemplateResult} from "lit";
import {customElement, eventOptions, property} from "lit/decorators.js";
import {repeat} from "lit/directives/repeat.js";
import {get, LanguageIdentifier, registerTranslateConfig, translate, translateUnsafeHTML, use} from "../../lib";

import styles from "./demo-page.scss";

const languages = [
"en",
"da"
"en",
"da"
];

// Registers loader
registerTranslateConfig({
loader: (lang: LanguageIdentifier) => fetch(`assets/i18n/${lang}.json`).then(res => res.json())
loader: (lang: LanguageIdentifier) => fetch(`assets/i18n/${lang}.json`).then(res => res.json())
});

// const testTranslateConfig: ITranslateConfig = {
Expand All @@ -28,67 +28,67 @@ registerTranslateConfig({
@customElement("demo-page-component")
export class DemoPageComponent extends LitElement {

@property() lang = languages[0];
@property() thing = "";
@property() lang = languages[0];
@property() thing = "";

// Defer the first update of the component until the strings has been loaded to avoid empty strings being shown
private hasLoadedStrings = false;
// Defer the first update of the component until the strings has been loaded to avoid empty strings being shown
private hasLoadedStrings = false;

protected shouldUpdate (changedProperties: PropertyValues) {
return this.hasLoadedStrings && super.shouldUpdate(changedProperties);
}
protected shouldUpdate(changedProperties: PropertyValues) {
return this.hasLoadedStrings && super.shouldUpdate(changedProperties);
}

// Load the initial language and mark that the strings has been loaded.
async connectedCallback () {
super.connectedCallback();
// Load the initial language and mark that the strings has been loaded.
async connectedCallback() {
super.connectedCallback();

await use(this.lang);
this.hasLoadedStrings = true;
this.requestUpdate();
await use(this.lang);
this.hasLoadedStrings = true;
this.requestUpdate();

// The below example is how parts of the strings could be lazy loaded
// listenForLangChanged(() => {
// setTimeout(async () => {
// const subpageStrings = await (await fetch(`./../assets/i18n/subpage-${translateConfig.lang}.json`)
// .then(d => d.json()));
//
// translateConfig.strings = {...translateConfig.strings, ...subpageStrings};
// translateConfig.translationCache = {};
//
// this.requestUpdate().then();
//
// console.log(translateConfig, get("subpage.title"));
// }, 2000);
// });
}
// The below example is how parts of the strings could be lazy loaded
// listenForLangChanged(() => {
// setTimeout(async () => {
// const subpageStrings = await (await fetch(`./../assets/i18n/subpage-${translateConfig.lang}.json`)
// .then(d => d.json()));
//
// translateConfig.strings = {...translateConfig.strings, ...subpageStrings};
// translateConfig.translationCache = {};
//
// this.requestUpdate().then();
//
// console.log(translateConfig, get("subpage.title"));
// }, 2000);
// });
}

@eventOptions({capture: true})
private async onLanguageSelected (e: Event) {
this.lang = (<HTMLSelectElement>e.target).value;
await use(this.lang).then();
}
@eventOptions({capture: true})
private async onLanguageSelected(e: Event) {
this.lang = (<HTMLSelectElement>e.target).value;
await use(this.lang).then();
}

protected render (): TemplateResult {
return html`
<style>
${styles}
</style>
protected render(): TemplateResult {
return html`
<style>
${styles}
</style>
<div id="box">
<h1>lit-translate</h1>
<p>${translate("lang")}</p>
<p>${translate("app.title")}</p>
<p>${translate("app.subtitle", () => ({thing: this.thing || get("world")}))}</p>
<p>${translateUnsafeHTML("app.html")}</p>
<select value="${this.lang}" @change="${this.onLanguageSelected}">
${repeat(languages, lang => html`
<option value="${lang}">${lang}</option>
`)}
</select>
<input placeholder="Your name"
@input="${(e: Event) => this.thing = (e.target as HTMLInputElement)!.value}"/>
</div>
<a href="https://github.com/andreasbm/lit-translate" target="_blank">View on Github</a>
`;
}
<div id="box">
<h1>lit-translate</h1>
<p>${translate("lang")}</p>
<p>${translate("app.title")}</p>
<p>${translate("app.subtitle", () => ({thing: this.thing || get("world")}))}</p>
<p>${translateUnsafeHTML("app.html")}</p>
<select value="${this.lang}" @change="${this.onLanguageSelected}">
${repeat(languages, lang => html`
<option value="${lang}">${lang}</option>
`)}
</select>
<input placeholder="Your name"
@input="${(e: Event) => this.thing = (e.target as HTMLInputElement)!.value}"/>
</div>
<a href="https://github.com/andreasbm/lit-translate" target="_blank">View on Github</a>
`;
}
}
62 changes: 62 additions & 0 deletions src/lib/directives/lang-changed-base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {AsyncDirective} from "lit/async-directive.js";
import {LangChangedEvent, LangChangedSubscription} from "../model";
import {listenForLangChanged} from "../util";

/**
* An abstract lit directive that reacts when the language changes.
*/
export abstract class LangChangedDirectiveBase extends AsyncDirective {
protected langChangedSubscription: LangChangedSubscription | null = null;
protected getValue: ((e?: LangChangedEvent) => unknown) = (() => "");

/**
* Sets up the directive by setting the getValue property and subscribing.
* When subclassing LangChangedDirectiveBase this function should be call in the render function.
* @param getValue
*/
renderValue(getValue: ((e?: LangChangedEvent) => unknown)): unknown {
this.getValue = getValue;
this.subscribe();
return this.getValue();
}

/**
* Called when the lang changed event is dispatched.
* @param e
*/
langChanged(e?: LangChangedEvent) {
this.setValue(this.getValue(e));
}

/**
* Subscribes to the lang changed event.
*/
subscribe() {
if (this.langChangedSubscription == null) {
this.langChangedSubscription = listenForLangChanged(this.langChanged.bind(this));
}
}

/**
* Unsubscribes from the lang changed event.
*/
unsubscribe() {
if (this.langChangedSubscription != null) {
this.langChangedSubscription();
}
}

/**
* Unsubscribes when disconnected.
*/
disconnected() {
this.unsubscribe();
}

/**
* Subscribes when reconnected.
*/
reconnected() {
this.subscribe();
}
}
14 changes: 14 additions & 0 deletions src/lib/directives/lang-changed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {directive} from "lit/directive.js";
import {LangChangedEvent} from "../model";
import {LangChangedDirectiveBase} from "./lang-changed-base";

/**
* A lit directive that reacts when the language changes and renders the getValue callback.
*/
export class LangChangedDirective extends LangChangedDirectiveBase {
render(getValue: ((e?: LangChangedEvent) => unknown)): unknown {
return this.renderValue(getValue);
}
}

export const langChanged = directive(LangChangedDirective);
21 changes: 8 additions & 13 deletions src/lib/directives/translate-unsafe-html.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import { directive } from "lit/directive.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { ITranslateConfig, Values, ValuesCallback } from "../model";
import { TranslateDirective } from "./translate";
import {directive} from "lit/directive.js";
import {unsafeHTML} from "lit/directives/unsafe-html.js";
import {ITranslateConfig, Values, ValuesCallback} from "../model";
import {TranslateDirective} from "./translate";
import {get} from "../util";

/**
* A lit directive that updates the translation as HTML when the language changes.
*/
export class TranslateUnsafeHTMLDirective extends TranslateDirective {
render (key: string, values?: Values | ValuesCallback, config?: ITranslateConfig) {
super.render(key, values, config);
return unsafeHTML(this.getTranslation());
}

updateTranslation () {
const translation = this.getTranslation();
this.setValue(unsafeHTML(translation));
}
render(key: string, values?: Values | ValuesCallback, config?: ITranslateConfig) {
return this.renderValue(() => unsafeHTML(get(key, values, config)));
}
}

export const translateUnsafeHTML = directive(TranslateUnsafeHTMLDirective);
47 changes: 8 additions & 39 deletions src/lib/directives/translate.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,15 @@
import { AsyncDirective } from "lit/async-directive.js";
import { directive } from "lit/directive.js";
import { ITranslateConfig, LangChangedSubscription, Translation, Values, ValuesCallback } from "../model";
import { get, listenForLangChanged } from "../util";
import {directive} from "lit/directive.js";
import {ITranslateConfig, Values, ValuesCallback} from "../model";
import {get} from "../util";
import {LangChangedDirectiveBase} from "./lang-changed-base";

/**
* A lit directive that updates the translation when the language changes.
*/
export class TranslateDirective extends AsyncDirective {
protected langChangedSubscription: LangChangedSubscription | null = null;
protected getTranslation: (() => Translation) = (() => "");

render (key: string, values?: Values | ValuesCallback, config?: ITranslateConfig): unknown {
this.getTranslation = () => get(key, values, config);
this.subscribe();
return this.getTranslation();
}

updateTranslation () {
const translation = this.getTranslation();
this.setValue(translation);
}

subscribe () {
if (this.langChangedSubscription == null) {
this.langChangedSubscription = listenForLangChanged(this.updateTranslation.bind(this));
}
}

unsubscribe () {
if (this.langChangedSubscription != null) {
this.langChangedSubscription();
}
}

disconnected () {
this.unsubscribe();
}

reconnected () {
this.subscribe();
}
export class TranslateDirective extends LangChangedDirectiveBase {
render(key: string, values?: Values | ValuesCallback, config?: ITranslateConfig): unknown {
return this.renderValue(() => get(key, values, config));
}
}

// Create the directive function
export const translate = directive(TranslateDirective);
2 changes: 2 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from "./util";
export * from "./helpers";
export * from "./directives/translate";
export * from "./directives/translate-unsafe-html";
export * from "./directives/lang-changed";
export * from "./directives/lang-changed-base";

0 comments on commit 2703f1b

Please sign in to comment.