From fbccf23d362b7ec43de472a875b348e8920f6250 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 14 Oct 2018 22:40:43 +0200 Subject: [PATCH] Clean up localize mixin (#1771) --- src/mixins/lit-localize-mixin.js | 52 +++ src/mixins/localize-base-mixin.js | 82 +++++ src/mixins/localize-lite-mixin.js | 21 +- src/mixins/localize-mixin.js | 34 +- src/panels/lovelace/cards/hui-glance-card.js | 8 +- src/panels/profile/ha-panel-profile.js | 2 + src/util/app-localize-behavior.js | 346 ------------------- 7 files changed, 168 insertions(+), 377 deletions(-) create mode 100644 src/mixins/lit-localize-mixin.js create mode 100644 src/mixins/localize-base-mixin.js delete mode 100644 src/util/app-localize-behavior.js diff --git a/src/mixins/lit-localize-mixin.js b/src/mixins/lit-localize-mixin.js new file mode 100644 index 0000000000..1433d8b5ca --- /dev/null +++ b/src/mixins/lit-localize-mixin.js @@ -0,0 +1,52 @@ +import { dedupingMixin } from "@polymer/polymer/lib/utils/mixin.js"; +import { LocalizeBaseMixin } from "./localize-base-mixin"; + +export const HassLocalizeLitMixin = dedupingMixin( + (superClass) => + class extends LocalizeBaseMixin(superClass) { + static get properties() { + return { + hass: {}, + localize: {}, + }; + } + + connectedCallback() { + super.connectedCallback(); + + let language; + let resources; + if (this.hass) { + language = this.hass.language; + resources = this.hass.resources; + } + this.localize = this.__computeLocalize(language, resources); + } + + updated(changedProperties) { + super.updated(changedProperties); + + if (!changedProperties.has("hass")) { + return; + } + + let oldLanguage; + let oldResources; + if (changedProperties.hass) { + oldLanguage = changedProperties.hass.language; + oldResources = changedProperties.hass.resources; + } + + let language; + let resources; + if (this.hass) { + language = this.hass.language; + resources = this.hass.resources; + } + + if (oldLanguage !== language || oldResources !== resources) { + this.localize = this.__computeLocalize(language, resources); + } + } + } +); diff --git a/src/mixins/localize-base-mixin.js b/src/mixins/localize-base-mixin.js new file mode 100644 index 0000000000..8b087143ed --- /dev/null +++ b/src/mixins/localize-base-mixin.js @@ -0,0 +1,82 @@ +import { dedupingMixin } from "@polymer/polymer/lib/utils/mixin.js"; +import IntlMessageFormat from "intl-messageformat/src/main.js"; + +/** +Adapted from Polymer app-localize-behavior. + +Copyright (c) 2016 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +export const LocalizeBaseMixin = dedupingMixin( + (superClass) => + class extends superClass { + /** + * Returns a computed `localize` method, based on the current `language`. + */ + __computeLocalize(language, resources, formats) { + const proto = this.constructor.prototype; + + // Check if localCache exist just in case. + this.__checkLocalizationCache(proto); + + // Everytime any of the parameters change, invalidate the strings cache. + if (!proto.__localizationCache) { + proto.__localizationCache = { + messages: {}, + }; + } + proto.__localizationCache.messages = {}; + + return (key, ...args) => { + if (!key || !resources || !language || !resources[language]) { + return ""; + } + + // Cache the key/value pairs for the same language, so that we don't + // do extra work if we're just reusing strings across an application. + const translatedValue = resources[language][key]; + + if (!translatedValue) { + return this.useKeyIfMissing ? key : ""; + } + + const messageKey = key + translatedValue; + let translatedMessage = + proto.__localizationCache.messages[messageKey]; + + if (!translatedMessage) { + translatedMessage = new IntlMessageFormat( + translatedValue, + language, + formats + ); + proto.__localizationCache.messages[messageKey] = translatedMessage; + } + + const argObject = {}; + for (let i = 0; i < args.length; i += 2) { + argObject[args[i]] = args[i + 1]; + } + + return translatedMessage.format(argObject); + }; + } + + __checkLocalizationCache(proto) { + // do nothing if proto is undefined. + if (proto === undefined) return; + + // In the event proto not have __localizationCache object, create it. + if (proto.__localizationCache === undefined) { + proto.__localizationCache = { + messages: {}, + }; + } + } + } +); diff --git a/src/mixins/localize-lite-mixin.js b/src/mixins/localize-lite-mixin.js index 24d146b5dc..53faf78ec4 100644 --- a/src/mixins/localize-lite-mixin.js +++ b/src/mixins/localize-lite-mixin.js @@ -1,9 +1,8 @@ /** * Lite mixin to add localization without depending on the Hass object. */ -import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class.js"; import { dedupingMixin } from "@polymer/polymer/lib/utils/mixin.js"; -import { AppLocalizeBehavior } from "../util/app-localize-behavior.js"; +import { LocalizeBaseMixin } from "./localize-base-mixin"; import { getActiveTranslation, getTranslation, @@ -11,11 +10,10 @@ import { /** * @polymerMixin - * @appliesMixin AppLocalizeBehavior */ export default dedupingMixin( (superClass) => - class extends mixinBehaviors([AppLocalizeBehavior], superClass) { + class extends LocalizeBaseMixin(superClass) { static get properties() { return { language: { @@ -25,10 +23,19 @@ export default dedupingMixin( resources: Object, // The fragment to load. translationFragment: String, + /** + * Translates a string to the current `language`. Any parameters to the + * string should be passed in order, as follows: + * `localize(stringKey, param1Name, param1Value, param2Name, param2Value)` + */ + localize: { + type: Function, + computed: "__computeLocalize(language, resources, formats)", + }, }; } - async ready() { + ready() { super.ready(); if (this.resources) { @@ -53,6 +60,10 @@ export default dedupingMixin( return; } + this._updateResources(); + } + + async _updateResources() { const { language, data } = await getTranslation( this.translationFragment ); diff --git a/src/mixins/localize-mixin.js b/src/mixins/localize-mixin.js index d81ccb0b41..d1a104d1d2 100644 --- a/src/mixins/localize-mixin.js +++ b/src/mixins/localize-mixin.js @@ -1,34 +1,28 @@ -import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class.js"; import { dedupingMixin } from "@polymer/polymer/lib/utils/mixin.js"; -import { AppLocalizeBehavior } from "../util/app-localize-behavior.js"; - +import { LocalizeBaseMixin } from "./localize-base-mixin.js"; /** + * Polymer Mixin to enable a localize function powered by language/resources from hass object. + * * @polymerMixin - * @appliesMixin AppLocalizeBehavior */ export default dedupingMixin( (superClass) => - class extends mixinBehaviors([AppLocalizeBehavior], superClass) { + class extends LocalizeBaseMixin(superClass) { static get properties() { return { hass: Object, - language: { - type: String, - computed: "computeLanguage(hass)", - }, - resources: { - type: Object, - computed: "computeResources(hass)", + + /** + * Translates a string to the current `language`. Any parameters to the + * string should be passed in order, as follows: + * `localize(stringKey, param1Name, param1Value, param2Name, param2Value)` + */ + localize: { + type: Function, + computed: + "__computeLocalize(hass.language, hass.resources, formats)", }, }; } - - computeLanguage(hass) { - return hass && hass.language; - } - - computeResources(hass) { - return hass && hass.resources; - } } ); diff --git a/src/panels/lovelace/cards/hui-glance-card.js b/src/panels/lovelace/cards/hui-glance-card.js index 47b60dfbe2..3524e1dee4 100644 --- a/src/panels/lovelace/cards/hui-glance-card.js +++ b/src/panels/lovelace/cards/hui-glance-card.js @@ -13,13 +13,9 @@ import "../../../components/ha-card.js"; import "../../../components/ha-icon.js"; import EventsMixin from "../../../mixins/events-mixin.js"; -import LocalizeMixin from "../../../mixins/localize-mixin.js"; +import { HassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin.js"; -/* - * @appliesMixin EventsMixin - * @appliesMixin LocalizeMixin - */ -class HuiGlanceCard extends LocalizeMixin(EventsMixin(LitElement)) { +class HuiGlanceCard extends HassLocalizeLitMixin(EventsMixin(LitElement)) { renderStyle() { return html`