mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Core POC support for polymer i18n (#227)
* Core POC support for polymer i18n * Move translation from core.js to html * Replace fetch with XHR * Convert translation pipeline to gulp * Convert from polyglot to Polymer localize * Pass through missing keys for custom panels * Store promise to be reused * Use cacheFirst sw handler for translations * Write full filenames to translationFingerprints * Precache en translation * Convert home-assistant-main to ES6 class * Create a localization mixin * Cleanup * Add polymer tags to annotate for linter * Rename fingerprints to translationMetadata * Build translation native names into metadata * Add language selection UI to sidebar * Provide separate message namespace argument * Store language/resources on hass object * Store translationMetadata on hass * Move language selector to config panel * Temporarily hide language selector * Small cleanups * Use dynamic-align for more flexible layout * Migrate to fetch API * Only send change events for user selection events * Update for new linting rules * Migrate build_frontend changes
This commit is contained in:
parent
7b61826134
commit
29fad98754
@ -9,6 +9,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-layout": "^2.0.0",
|
"app-layout": "^2.0.0",
|
||||||
|
"app-localize-behavior": "PolymerElements/app-localize-behavior#~2.0.0",
|
||||||
"app-route": "PolymerElements/app-route#^2.0.0",
|
"app-route": "PolymerElements/app-route#^2.0.0",
|
||||||
"app-storage": "^2.0.2",
|
"app-storage": "^2.0.2",
|
||||||
"fecha": "~2.3.0",
|
"fecha": "~2.3.0",
|
||||||
|
@ -30,7 +30,7 @@ function renamePanel(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('build', ['ru_all'], () => {
|
gulp.task('build', ['ru_all', 'build-translations'], () => {
|
||||||
const strategy = composeStrategies([
|
const strategy = composeStrategies([
|
||||||
generateShellMergeStrategy(polymerConfig.shell),
|
generateShellMergeStrategy(polymerConfig.shell),
|
||||||
stripImportsStrategy([
|
stripImportsStrategy([
|
||||||
|
@ -39,6 +39,7 @@ var staticFingerprinted = [
|
|||||||
'mdi.html',
|
'mdi.html',
|
||||||
'core.js',
|
'core.js',
|
||||||
'compatibility.js',
|
'compatibility.js',
|
||||||
|
'translations/en.json',
|
||||||
];
|
];
|
||||||
|
|
||||||
// These panels will always be registered inside HA and thus can
|
// These panels will always be registered inside HA and thus can
|
||||||
@ -62,9 +63,10 @@ gulp.task('gen-service-worker', () => {
|
|||||||
// Create fingerprinted versions of our dependencies.
|
// Create fingerprinted versions of our dependencies.
|
||||||
staticFingerprinted.forEach(fn => {
|
staticFingerprinted.forEach(fn => {
|
||||||
var parts = path.parse(fn);
|
var parts = path.parse(fn);
|
||||||
var hash = md5(rootDir + '/' + parts.name + parts.ext);
|
var base = parts.dir.length > 0 ? parts.dir + '/' + parts.name : parts.name;
|
||||||
var url = '/static/' + parts.name + '-' + hash + parts.ext;
|
var hash = md5(rootDir + '/' + base + parts.ext);
|
||||||
var fpath = rootDir + '/' + parts.name + parts.ext;
|
var url = '/static/' + base + '-' + hash + parts.ext;
|
||||||
|
var fpath = rootDir + '/' + base + parts.ext;
|
||||||
dynamicUrlToDependencies[url] = [fpath];
|
dynamicUrlToDependencies[url] = [fpath];
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,6 +91,10 @@ gulp.task('gen-service-worker', () => {
|
|||||||
rootDir + '/fonts/roboto/Roboto-Bold.ttf',
|
rootDir + '/fonts/roboto/Roboto-Bold.ttf',
|
||||||
rootDir + '/images/card_media_player_bg.png',
|
rootDir + '/images/card_media_player_bg.png',
|
||||||
],
|
],
|
||||||
|
runtimeCaching: [{
|
||||||
|
urlPattern: /\/static\/translations\//,
|
||||||
|
handler: 'cacheFirst',
|
||||||
|
}],
|
||||||
stripPrefix: 'hass_frontend',
|
stripPrefix: 'hass_frontend',
|
||||||
replacePrefix: 'static',
|
replacePrefix: 'static',
|
||||||
verbose: true,
|
verbose: true,
|
||||||
|
111
gulp/tasks/translations.js
Executable file
111
gulp/tasks/translations.js
Executable file
@ -0,0 +1,111 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const foreach = require('gulp-foreach');
|
||||||
|
const hash = require('gulp-hash');
|
||||||
|
const insert = require('gulp-insert');
|
||||||
|
const merge = require('gulp-merge-json');
|
||||||
|
const minify = require('gulp-jsonminify');
|
||||||
|
const rename = require('gulp-rename');
|
||||||
|
const transform = require('gulp-json-transform');
|
||||||
|
|
||||||
|
const inDir = 'translations'
|
||||||
|
const outDir = 'build/translations';
|
||||||
|
|
||||||
|
const tasks = [];
|
||||||
|
|
||||||
|
function recursive_flatten (prefix, data) {
|
||||||
|
var output = {};
|
||||||
|
Object.keys(data).forEach(function (key) {
|
||||||
|
if (typeof(data[key]) === 'object') {
|
||||||
|
output = Object.assign({}, output, recursive_flatten(key + '.', data[key]));
|
||||||
|
} else {
|
||||||
|
output[prefix + key] = data[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
function flatten (data) {
|
||||||
|
return recursive_flatten('', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var taskName = 'build-translation-native-names';
|
||||||
|
gulp.task(taskName, function() {
|
||||||
|
return gulp.src(inDir + '/*.json')
|
||||||
|
.pipe(transform(function(data, file) {
|
||||||
|
// Look up the native name for each language and generate a json
|
||||||
|
// object with all available languages and native names
|
||||||
|
const lang = path.basename(file.relative, '.json');
|
||||||
|
return {[lang]: {nativeName: data.language[lang]}};
|
||||||
|
}))
|
||||||
|
.pipe(merge({
|
||||||
|
fileName: 'translationNativeNames.json',
|
||||||
|
}))
|
||||||
|
.pipe(gulp.dest('build-temp'));
|
||||||
|
});
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
var taskName = 'build-merged-translations';
|
||||||
|
gulp.task(taskName, function () {
|
||||||
|
return gulp.src(inDir + '/*.json')
|
||||||
|
.pipe(foreach(function(stream, file) {
|
||||||
|
// For each language generate a merged json file. It begins with en.json as
|
||||||
|
// a failsafe for untranslated strings, and merges all parent tags into one
|
||||||
|
// file for each specific subtag
|
||||||
|
const tr = path.basename(file.history[0], '.json');
|
||||||
|
const subtags = tr.split('-');
|
||||||
|
const src = [inDir + '/en.json']; // Start with en as a fallback for missing translations
|
||||||
|
for (i = 1; i <= subtags.length; i++) {
|
||||||
|
const lang = subtags.slice(0, i).join('-');
|
||||||
|
src.push(inDir + '/' + lang + '.json');
|
||||||
|
}
|
||||||
|
return gulp.src(src)
|
||||||
|
.pipe(merge({
|
||||||
|
fileName: tr + '.json',
|
||||||
|
}))
|
||||||
|
.pipe(transform(function(data, file) {
|
||||||
|
// Polymer.AppLocalizeBehavior requires flattened json
|
||||||
|
return flatten(data);
|
||||||
|
}))
|
||||||
|
.pipe(minify())
|
||||||
|
.pipe(gulp.dest(outDir));
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
var taskName = 'build-translation-fingerprints';
|
||||||
|
gulp.task(taskName, ['build-merged-translations'], function() {
|
||||||
|
return gulp.src(outDir + '/*.json')
|
||||||
|
.pipe(rename({
|
||||||
|
extname: "",
|
||||||
|
}))
|
||||||
|
.pipe(hash({
|
||||||
|
algorithm: 'md5',
|
||||||
|
hashLength: 32,
|
||||||
|
template: '<%= name %>-<%= hash %>.json',
|
||||||
|
}))
|
||||||
|
.pipe(hash.manifest('translationFingerprints.json'))
|
||||||
|
.pipe(transform(function(data, file) {
|
||||||
|
Object.keys(data).map(function(key, index) {
|
||||||
|
data[key] = {fingerprint: data[key]};
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}))
|
||||||
|
.pipe(gulp.dest('build-temp'));
|
||||||
|
});
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
var taskName = 'build-translations';
|
||||||
|
gulp.task(taskName, ['build-translation-fingerprints', 'build-translation-native-names'], function() {
|
||||||
|
return gulp.src([
|
||||||
|
'build-temp/translationFingerprints.json',
|
||||||
|
'build-temp/translationNativeNames.json',
|
||||||
|
])
|
||||||
|
.pipe(merge({}))
|
||||||
|
.pipe(insert.wrap('<script>\nwindow.translationMetadata = ', ';\n</script>'))
|
||||||
|
.pipe(rename('translationMetadata.html'))
|
||||||
|
.pipe(gulp.dest('build-temp'));
|
||||||
|
});
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
module.exports = tasks;
|
@ -39,8 +39,14 @@
|
|||||||
"gulp-babel": "^7.0.0",
|
"gulp-babel": "^7.0.0",
|
||||||
"gulp-file": "^0.3.0",
|
"gulp-file": "^0.3.0",
|
||||||
"gulp-filter": "^5.0.1",
|
"gulp-filter": "^5.0.1",
|
||||||
|
"gulp-foreach": "^0.1.0",
|
||||||
|
"gulp-hash": "^4.0.1",
|
||||||
"gulp-html-minifier": "^0.1.8",
|
"gulp-html-minifier": "^0.1.8",
|
||||||
"gulp-if": "^2.0.2",
|
"gulp-if": "^2.0.2",
|
||||||
|
"gulp-insert": "^0.5.0",
|
||||||
|
"gulp-json-transform": "^0.4.2",
|
||||||
|
"gulp-jsonminify": "^1.0.0",
|
||||||
|
"gulp-merge-json": "^1.0.0",
|
||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-rollup-each": "^2.0.0",
|
"gulp-rollup-each": "^2.0.0",
|
||||||
"gulp-uglify": "^3.0.0",
|
"gulp-uglify": "^3.0.0",
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<link rel="import" href="./ha-config-section-core.html">
|
<link rel="import" href="./ha-config-section-core.html">
|
||||||
<!-- <link rel="import" href="./ha-config-section-group.html"> -->
|
<!-- <link rel="import" href="./ha-config-section-group.html"> -->
|
||||||
<link rel="import" href="./ha-config-section-hassbian.html">
|
<link rel="import" href="./ha-config-section-hassbian.html">
|
||||||
|
<link rel="import" href="./ha-config-section-translation.html">
|
||||||
<link rel="import" href="./ha-config-section-themes.html">
|
<link rel="import" href="./ha-config-section-themes.html">
|
||||||
|
|
||||||
<dom-module id="ha-config-core">
|
<dom-module id="ha-config-core">
|
||||||
@ -53,6 +54,14 @@
|
|||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
></ha-config-section-core>
|
></ha-config-section-core>
|
||||||
|
|
||||||
|
<template is='dom-if' if='[[computeIsTranslationLoaded(hass)]]'>
|
||||||
|
<div class='border'></div>
|
||||||
|
<ha-config-section-translation
|
||||||
|
is-wide='[[isWide]]'
|
||||||
|
hass='[[hass]]'
|
||||||
|
></ha-config-section-translation>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template is='dom-if' if='[[computeIsThemesLoaded(hass)]]'>
|
<template is='dom-if' if='[[computeIsThemesLoaded(hass)]]'>
|
||||||
<div class='border'></div>
|
<div class='border'></div>
|
||||||
<ha-config-section-themes
|
<ha-config-section-themes
|
||||||
@ -96,6 +105,13 @@ class HaConfigCore extends Polymer.Element {
|
|||||||
return window.hassUtil.isComponentLoaded(hass, 'config.zwave');
|
return window.hassUtil.isComponentLoaded(hass, 'config.zwave');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
computeIsTranslationLoaded(hass) {
|
||||||
|
// Return false to hide language selection until i18n is ready to be
|
||||||
|
// deployed.
|
||||||
|
return false && hass.translationMetadata &&
|
||||||
|
Object.keys(hass.translationMetadata).length;
|
||||||
|
}
|
||||||
|
|
||||||
computeIsThemesLoaded(hass) {
|
computeIsThemesLoaded(hass) {
|
||||||
return hass.themes && hass.themes.themes &&
|
return hass.themes && hass.themes.themes &&
|
||||||
Object.keys(hass.themes.themes).length;
|
Object.keys(hass.themes.themes).length;
|
||||||
|
79
panels/config/core/ha-config-section-translation.html
Normal file
79
panels/config/core/ha-config-section-translation.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
|
||||||
|
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
|
||||||
|
|
||||||
|
<link rel='import' href='../../../src/util/hass-mixins.html'>
|
||||||
|
<link rel="import" href="../ha-config-section.html">
|
||||||
|
|
||||||
|
<dom-module id="ha-config-section-translation">
|
||||||
|
<template>
|
||||||
|
<ha-config-section is-wide='[[isWide]]'>
|
||||||
|
<span slot='header'>Choose a Language</span>
|
||||||
|
<span slot='introduction'>
|
||||||
|
Choose a language for the Home Assistant interface on this device.
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<paper-card>
|
||||||
|
<div class='card-content'>
|
||||||
|
<paper-dropdown-menu label="Language" dynamic-align>
|
||||||
|
<paper-listbox slot="dropdown-content" on-selected-item-changed="handleLanguageSelect" attr-for-selected="language-tag" selected="[[language]]">
|
||||||
|
<template is='dom-repeat' items='[[languages]]'>
|
||||||
|
<paper-item language-tag="[[item.tag]]">[[item.nativeName]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-listbox>
|
||||||
|
></paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</ha-config-section>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/*
|
||||||
|
* @appliesMixin window.hassMixins.LocalizeMixin
|
||||||
|
* @appliesMixin window.hassMixins.EventsMixin
|
||||||
|
*/
|
||||||
|
class HaConfigSectionTranslation extends
|
||||||
|
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
|
||||||
|
static get is() { return 'ha-config-section-translation'; }
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
isWide: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
languages: {
|
||||||
|
type: Array,
|
||||||
|
computed: 'computeLanguages(hass)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
computeLanguages(hass) {
|
||||||
|
if (!hass || !hass.translationMetadata) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.keys(hass.translationMetadata).map(key => ({
|
||||||
|
tag: key,
|
||||||
|
nativeName: hass.translationMetadata[key].nativeName,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLanguageSelect(ev) {
|
||||||
|
// Only fire event if language was changed. This prevents select updates when
|
||||||
|
// responding to hass changes.
|
||||||
|
if (ev.detail.value && ev.detail.value.languageTag !== this.language) {
|
||||||
|
this.fire('hass-language-select', { language: ev.detail.value.languageTag });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define(HaConfigSectionTranslation.is, HaConfigSectionTranslation);
|
||||||
|
</script>
|
@ -21,6 +21,10 @@ cp build/*.js build/*.html $OUTPUT_DIR
|
|||||||
mkdir $OUTPUT_DIR/panels
|
mkdir $OUTPUT_DIR/panels
|
||||||
cp build/panels/*.html $OUTPUT_DIR/panels
|
cp build/panels/*.html $OUTPUT_DIR/panels
|
||||||
|
|
||||||
|
# Panels
|
||||||
|
mkdir $OUTPUT_DIR/translations
|
||||||
|
cp build/translations/*.json $OUTPUT_DIR/translations
|
||||||
|
|
||||||
# Local Roboto
|
# Local Roboto
|
||||||
cp -r bower_components/font-roboto-local/fonts $OUTPUT_DIR
|
cp -r bower_components/font-roboto-local/fonts $OUTPUT_DIR
|
||||||
|
|
||||||
@ -43,7 +47,13 @@ cp build/service_worker.js $OUTPUT_DIR
|
|||||||
|
|
||||||
# GZIP frontend
|
# GZIP frontend
|
||||||
cd $OUTPUT_DIR
|
cd $OUTPUT_DIR
|
||||||
gzip -f -n -k -9 *.html *.js ./panels/*.html ./fonts/roboto/*.ttf ./fonts/robotomono/*.ttf
|
gzip -f -n -k -9 \
|
||||||
|
*.html \
|
||||||
|
*.js \
|
||||||
|
./panels/*.html \
|
||||||
|
./translations/*.json \
|
||||||
|
./fonts/roboto/*.ttf \
|
||||||
|
./fonts/robotomono/*.ttf
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Generate the __init__ file
|
# Generate the __init__ file
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||||
|
|
||||||
<link rel='import' href='../util/hass-mixins.html'>
|
<link rel='import' href='../util/hass-mixins.html'>
|
||||||
|
<link rel='import' href='../util/hass-translation.html'>
|
||||||
|
|
||||||
<link rel='import' href='./ha-push-notifications-toggle.html'>
|
<link rel='import' href='./ha-push-notifications-toggle.html'>
|
||||||
|
|
||||||
@ -105,19 +106,19 @@
|
|||||||
<paper-listbox attr-for-selected='data-panel' selected='[[route.panel]]'>
|
<paper-listbox attr-for-selected='data-panel' selected='[[route.panel]]'>
|
||||||
<paper-icon-item on-tap='menuClicked' data-panel='states'>
|
<paper-icon-item on-tap='menuClicked' data-panel='states'>
|
||||||
<iron-icon slot="item-icon" icon='mdi:apps'></iron-icon>
|
<iron-icon slot="item-icon" icon='mdi:apps'></iron-icon>
|
||||||
<span class='item-text'>States</span>
|
<span class='item-text'>{{localize('panel', 'states')}}</span>
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
|
|
||||||
<template is='dom-repeat' items='[[panels]]'>
|
<template is='dom-repeat' items='[[panels]]'>
|
||||||
<paper-icon-item on-tap='menuClicked' data-panel$='[[item.url_path]]'>
|
<paper-icon-item on-tap='menuClicked' data-panel$='[[item.url_path]]'>
|
||||||
<iron-icon slot="item-icon" icon='[[item.icon]]'></iron-icon>
|
<iron-icon slot="item-icon" icon='[[item.icon]]'></iron-icon>
|
||||||
<span class='item-text'>[[item.title]]</span>
|
<span class='item-text'>{{localize('panel', item.title)}}</span>
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<paper-icon-item on-tap='menuClicked' data-panel='logout' class='logout'>
|
<paper-icon-item on-tap='menuClicked' data-panel='logout' class='logout'>
|
||||||
<iron-icon slot="item-icon" icon='mdi:exit-to-app'></iron-icon>
|
<iron-icon slot="item-icon" icon='mdi:exit-to-app'></iron-icon>
|
||||||
<span class='item-text'>Log Out</span>
|
<span class='item-text'>{{localize('panel', 'log_out')}}</span>
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</paper-listbox>
|
</paper-listbox>
|
||||||
|
|
||||||
@ -171,7 +172,12 @@
|
|||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
class HaSidebar extends window.hassMixins.EventsMixin(Polymer.Element) {
|
/*
|
||||||
|
* @appliesMixin window.hassMixins.LocalizeMixin
|
||||||
|
* @appliesMixin window.hassMixins.EventsMixin
|
||||||
|
*/
|
||||||
|
class HaSidebar extends
|
||||||
|
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
|
||||||
static get is() { return 'ha-sidebar'; }
|
static get is() { return 'ha-sidebar'; }
|
||||||
|
|
||||||
static get properties() {
|
static get properties() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<link rel="import" href='../bower_components/polymer/polymer-element.html'>
|
<link rel="import" href='../bower_components/polymer/polymer-element.html'>
|
||||||
|
<link rel='import' href='../bower_components/app-localize-behavior/app-localize-behavior.html'>
|
||||||
<link rel='import' href='./util/roboto.html'>
|
<link rel='import' href='./util/roboto.html'>
|
||||||
<link rel='import' href='../bower_components/paper-styles/typography.html'>
|
<link rel='import' href='../bower_components/paper-styles/typography.html'>
|
||||||
<link rel='import' href='../bower_components/iron-flex-layout/iron-flex-layout-classes.html'>
|
<link rel='import' href='../bower_components/iron-flex-layout/iron-flex-layout-classes.html'>
|
||||||
@ -7,6 +8,7 @@
|
|||||||
<link rel="import" href="../bower_components/neon-animation/web-animations.html">
|
<link rel="import" href="../bower_components/neon-animation/web-animations.html">
|
||||||
|
|
||||||
|
|
||||||
|
<link rel='import' href='./util/hass-translation.html'>
|
||||||
<link rel='import' href='./util/hass-util.html'>
|
<link rel='import' href='./util/hass-util.html'>
|
||||||
<link rel='import' href='./util/ha-pref-storage.html'>
|
<link rel='import' href='./util/ha-pref-storage.html'>
|
||||||
<link rel='import' href='./util/hass-call-api.html'>
|
<link rel='import' href='./util/hass-call-api.html'>
|
||||||
@ -84,7 +86,9 @@ class HomeAssistant extends Polymer.Element {
|
|||||||
ready() {
|
ready() {
|
||||||
super.ready();
|
super.ready();
|
||||||
this.addEventListener('settheme', e => this.setTheme(e));
|
this.addEventListener('settheme', e => this.setTheme(e));
|
||||||
|
this.addEventListener('hass-language-select', e => this.selectLanguage(e));
|
||||||
this.loadIcons();
|
this.loadIcons();
|
||||||
|
this.loadResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
computeShowMain(hass, iconsLoaded) {
|
computeShowMain(hass, iconsLoaded) {
|
||||||
@ -112,6 +116,15 @@ class HomeAssistant extends Polymer.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadResources() {
|
||||||
|
window.getTranslation().then((result) => {
|
||||||
|
this._updateHass({
|
||||||
|
language: result.language,
|
||||||
|
resources: result.resources,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
connectionChanged(conn, oldConn) {
|
connectionChanged(conn, oldConn) {
|
||||||
if (oldConn) {
|
if (oldConn) {
|
||||||
this.unsubConnection();
|
this.unsubConnection();
|
||||||
@ -128,6 +141,9 @@ class HomeAssistant extends Polymer.Element {
|
|||||||
states: null,
|
states: null,
|
||||||
config: null,
|
config: null,
|
||||||
themes: null,
|
themes: null,
|
||||||
|
language: null,
|
||||||
|
resources: null,
|
||||||
|
translationMetadata: window.translationMetadata,
|
||||||
dockedSidebar: false,
|
dockedSidebar: false,
|
||||||
moreInfoEntityId: null,
|
moreInfoEntityId: null,
|
||||||
callService: (domain, service, serviceData) =>
|
callService: (domain, service, serviceData) =>
|
||||||
@ -256,6 +272,12 @@ class HomeAssistant extends Polymer.Element {
|
|||||||
this.$.storage.storeState();
|
this.$.storage.storeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectLanguage(event) {
|
||||||
|
this._updateHass({ selectedLanguage: event.detail.language });
|
||||||
|
this.$.storage.storeState();
|
||||||
|
this.loadResources();
|
||||||
|
}
|
||||||
|
|
||||||
_updateHass(obj) {
|
_updateHass(obj) {
|
||||||
this.hass = Object.assign({}, this.hass, obj);
|
this.hass = Object.assign({}, this.hass, obj);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
var STORED_STATE = [
|
var STORED_STATE = [
|
||||||
'dockedSidebar',
|
'dockedSidebar',
|
||||||
'selectedTheme',
|
'selectedTheme',
|
||||||
|
'selectedLanguage',
|
||||||
];
|
];
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
|
@ -77,4 +77,37 @@ window.hassMixins.NavigateMixin = Polymer.dedupingMixin(superClass =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* @polymerMixin */
|
||||||
|
window.hassMixins.LocalizeMixin = Polymer.dedupingMixin(superClass =>
|
||||||
|
class extends Polymer.mixinBehaviors([Polymer.AppLocalizeBehavior], superClass) {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
type: String,
|
||||||
|
computed: 'computeLanguage(hass)',
|
||||||
|
},
|
||||||
|
resources: {
|
||||||
|
type: Object,
|
||||||
|
computed: 'computeResources(hass)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
computeLanguage(hass) {
|
||||||
|
return hass && hass.language;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeResources(hass) {
|
||||||
|
return hass && hass.resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
localize(namespace, message, ...args) {
|
||||||
|
// Return the input message if no translation is found
|
||||||
|
return super.localize(namespace + '.' + message, ...args) || message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
84
src/util/hass-translation.html
Normal file
84
src/util/hass-translation.html
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<link rel='import' href='../../build-temp/translationMetadata.html' />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function getActiveTranslation() {
|
||||||
|
// Perform case-insenstive comparison since browser isn't required to
|
||||||
|
// report languages with specific cases.
|
||||||
|
const lookup = {};
|
||||||
|
/* eslint-disable no-undef */
|
||||||
|
Object.keys(window.translationMetadata).forEach(function (tr) {
|
||||||
|
lookup[tr.toLowerCase()] = tr;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Search for a matching translation from most specific to general
|
||||||
|
function languageGetTranslation(language) {
|
||||||
|
const subtags = language.toLowerCase().split('-');
|
||||||
|
|
||||||
|
for (var i = subtags.length; i >= 1; i--) {
|
||||||
|
const lang = subtags.slice(0, i).join('-');
|
||||||
|
|
||||||
|
if (lookup[lang]) {
|
||||||
|
return lookup[lang];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var translation = null;
|
||||||
|
if (window.localStorage.selectedLanguage) {
|
||||||
|
translation = languageGetTranslation(JSON.parse(window.localStorage.selectedLanguage));
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
} else if (navigator.languages) {
|
||||||
|
for (var i = 0; i < navigator.languages.length; i++) {
|
||||||
|
translation = languageGetTranslation(navigator.languages[i]);
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
translation = languageGetTranslation(navigator.language || navigator.userLanguage);
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final fallback
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store loaded translations in memory so translations are available immediately
|
||||||
|
// when DOM is created in Polymer. Even a cache lookup creates noticable latency.
|
||||||
|
const translations = {};
|
||||||
|
|
||||||
|
window.getTranslation = function (translationInput) {
|
||||||
|
const translation = translationInput || getActiveTranslation();
|
||||||
|
const translationFingerprint = window.translationMetadata[translation].fingerprint;
|
||||||
|
|
||||||
|
// Create a promise to fetch translation from the server
|
||||||
|
if (!translations[translationFingerprint]) {
|
||||||
|
translations[translationFingerprint] =
|
||||||
|
fetch('/static/translations/' + translationFingerprint)
|
||||||
|
.then(response => response.json()).then(data => ({
|
||||||
|
language: translation,
|
||||||
|
resources: {
|
||||||
|
[translation]: data
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
.catch((error) => {
|
||||||
|
delete translations[translationFingerprint];
|
||||||
|
if (translationInput !== 'en') {
|
||||||
|
// Couldn't load selected translation. Try a fall back to en before failing.
|
||||||
|
return window.getTranslation('en');
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return translations[translationFingerprint];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load selected translation into memory immediately so it is ready when Polymer
|
||||||
|
// initializes.
|
||||||
|
window.getTranslation();
|
||||||
|
</script>
|
12
translations/en.json
Normal file
12
translations/en.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"language": {
|
||||||
|
"en": "English"
|
||||||
|
},
|
||||||
|
"panel": {
|
||||||
|
"states": "States",
|
||||||
|
"map": "Map",
|
||||||
|
"logbook": "Logbook",
|
||||||
|
"history": "History",
|
||||||
|
"log_out": "Log Out"
|
||||||
|
}
|
||||||
|
}
|
164
yarn.lock
164
yarn.lock
@ -2378,6 +2378,10 @@ depd@~1.0.0:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa"
|
||||||
|
|
||||||
|
deprecate@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8"
|
||||||
|
|
||||||
deprecated@^0.0.1:
|
deprecated@^0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
|
resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
|
||||||
@ -2673,7 +2677,7 @@ es6-object-assign@^1.1.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
|
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
|
||||||
|
|
||||||
es6-promise@^2.1.0:
|
es6-promise@^2.1.0, es6-promise@^2.1.1:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
|
||||||
|
|
||||||
@ -3646,6 +3650,23 @@ gulp-filter@^5.0.1:
|
|||||||
multimatch "^2.0.0"
|
multimatch "^2.0.0"
|
||||||
streamfilter "^1.0.5"
|
streamfilter "^1.0.5"
|
||||||
|
|
||||||
|
gulp-foreach@^0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-foreach/-/gulp-foreach-0.1.0.tgz#2547abfd1a1b75f569b54194190ef1c0b0289538"
|
||||||
|
dependencies:
|
||||||
|
gulp-util "~2.2.14"
|
||||||
|
through2 "~0.6.3"
|
||||||
|
|
||||||
|
gulp-hash@^4.0.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-hash/-/gulp-hash-4.1.1.tgz#7779910f6c378686b62f88abbb57ebeef20945d0"
|
||||||
|
dependencies:
|
||||||
|
es6-promise "^2.1.1"
|
||||||
|
gulp-util "^2.2.17"
|
||||||
|
lodash.assign "^2.4.1"
|
||||||
|
lodash.template "^2.4.1"
|
||||||
|
through2 "^2.0.0"
|
||||||
|
|
||||||
gulp-html-minifier@^0.1.8:
|
gulp-html-minifier@^0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-html-minifier/-/gulp-html-minifier-0.1.8.tgz#b0dd99d96ad01c0a88d79465ed44f94d6a2b549a"
|
resolved "https://registry.yarnpkg.com/gulp-html-minifier/-/gulp-html-minifier-0.1.8.tgz#b0dd99d96ad01c0a88d79465ed44f94d6a2b549a"
|
||||||
@ -3663,12 +3684,45 @@ gulp-if@^2.0.0, gulp-if@^2.0.2:
|
|||||||
ternary-stream "^2.0.1"
|
ternary-stream "^2.0.1"
|
||||||
through2 "^2.0.1"
|
through2 "^2.0.1"
|
||||||
|
|
||||||
|
gulp-insert@^0.5.0:
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-insert/-/gulp-insert-0.5.0.tgz#32313f13e4a23cf5acca5ce5f0c080923c778602"
|
||||||
|
dependencies:
|
||||||
|
readable-stream "^1.0.26-4"
|
||||||
|
streamqueue "0.0.6"
|
||||||
|
|
||||||
|
gulp-json-transform@^0.4.2:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-json-transform/-/gulp-json-transform-0.4.2.tgz#2245ed252fa309c97b8bdd9d1a19cdd149e32685"
|
||||||
|
dependencies:
|
||||||
|
gulp-util "^3.0.7"
|
||||||
|
promise "^7.1.1"
|
||||||
|
through2 "^2.0.1"
|
||||||
|
|
||||||
|
gulp-jsonminify@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-jsonminify/-/gulp-jsonminify-1.0.0.tgz#c42b68812c657e6e0a12e93c2aa217b3eb38c70a"
|
||||||
|
dependencies:
|
||||||
|
gulp-util "~3.0.4"
|
||||||
|
jsonminify "~0.2.3"
|
||||||
|
through2 "~0.6.5"
|
||||||
|
|
||||||
gulp-match@^1.0.3:
|
gulp-match@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.3.tgz#91c7c0d7f29becd6606d57d80a7f8776a87aba8e"
|
resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.3.tgz#91c7c0d7f29becd6606d57d80a7f8776a87aba8e"
|
||||||
dependencies:
|
dependencies:
|
||||||
minimatch "^3.0.3"
|
minimatch "^3.0.3"
|
||||||
|
|
||||||
|
gulp-merge-json@^1.0.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gulp-merge-json/-/gulp-merge-json-1.2.0.tgz#8b68f297505278a8143a6fa5bb9830192e4e3ea1"
|
||||||
|
dependencies:
|
||||||
|
deprecate "^1.0.0"
|
||||||
|
gulp-util "^3.0.8"
|
||||||
|
json5 "^0.5.1"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
through "^2.3.8"
|
||||||
|
|
||||||
gulp-rename@^1.2.2:
|
gulp-rename@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817"
|
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817"
|
||||||
@ -3703,7 +3757,7 @@ gulp-uglify@^3.0.0:
|
|||||||
uglify-js "^3.0.5"
|
uglify-js "^3.0.5"
|
||||||
vinyl-sourcemaps-apply "^0.2.0"
|
vinyl-sourcemaps-apply "^0.2.0"
|
||||||
|
|
||||||
gulp-util@^2.2.14, gulp-util@^2.2.20:
|
gulp-util@^2.2.14, gulp-util@^2.2.17, gulp-util@^2.2.20, gulp-util@~2.2.14:
|
||||||
version "2.2.20"
|
version "2.2.20"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c"
|
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3716,7 +3770,7 @@ gulp-util@^2.2.14, gulp-util@^2.2.20:
|
|||||||
through2 "^0.5.0"
|
through2 "^0.5.0"
|
||||||
vinyl "^0.2.1"
|
vinyl "^0.2.1"
|
||||||
|
|
||||||
gulp-util@^3.0.0, gulp-util@^3.0.6, gulp-util@^3.0.8:
|
gulp-util@^3.0.0, gulp-util@^3.0.6, gulp-util@^3.0.7, gulp-util@^3.0.8, gulp-util@~3.0.4:
|
||||||
version "3.0.8"
|
version "3.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4488,6 +4542,10 @@ jsonify@~0.0.0:
|
|||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||||
|
|
||||||
|
jsonminify@~0.2.3:
|
||||||
|
version "0.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsonminify/-/jsonminify-0.2.3.tgz#4b842c8a3fe5d6aa48b2f8f95a1cf9a80c019d8e"
|
||||||
|
|
||||||
jsonpointer@^4.0.0:
|
jsonpointer@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
||||||
@ -4608,6 +4666,15 @@ lodash._baseassign@^3.0.0:
|
|||||||
lodash._basecopy "^3.0.0"
|
lodash._basecopy "^3.0.0"
|
||||||
lodash.keys "^3.0.0"
|
lodash.keys "^3.0.0"
|
||||||
|
|
||||||
|
lodash._basebind@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basebind/-/lodash._basebind-2.4.1.tgz#e940b9ebdd27c327e0a8dab1b55916c5341e9575"
|
||||||
|
dependencies:
|
||||||
|
lodash._basecreate "~2.4.1"
|
||||||
|
lodash._setbinddata "~2.4.1"
|
||||||
|
lodash._slice "~2.4.1"
|
||||||
|
lodash.isobject "~2.4.1"
|
||||||
|
|
||||||
lodash._basecopy@^3.0.0:
|
lodash._basecopy@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
|
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
|
||||||
@ -4616,6 +4683,32 @@ lodash._basecreate@^3.0.0:
|
|||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
|
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
|
||||||
|
|
||||||
|
lodash._basecreate@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz#f8e6f5b578a9e34e541179b56b8eeebf4a287e08"
|
||||||
|
dependencies:
|
||||||
|
lodash._isnative "~2.4.1"
|
||||||
|
lodash.isobject "~2.4.1"
|
||||||
|
lodash.noop "~2.4.1"
|
||||||
|
|
||||||
|
lodash._basecreatecallback@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz#7d0b267649cb29e7a139d0103b7c11fae84e4851"
|
||||||
|
dependencies:
|
||||||
|
lodash._setbinddata "~2.4.1"
|
||||||
|
lodash.bind "~2.4.1"
|
||||||
|
lodash.identity "~2.4.1"
|
||||||
|
lodash.support "~2.4.1"
|
||||||
|
|
||||||
|
lodash._basecreatewrapper@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz#4d31f2e7de7e134fbf2803762b8150b32519666f"
|
||||||
|
dependencies:
|
||||||
|
lodash._basecreate "~2.4.1"
|
||||||
|
lodash._setbinddata "~2.4.1"
|
||||||
|
lodash._slice "~2.4.1"
|
||||||
|
lodash.isobject "~2.4.1"
|
||||||
|
|
||||||
lodash._basetostring@^3.0.0:
|
lodash._basetostring@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5"
|
resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5"
|
||||||
@ -4624,6 +4717,15 @@ lodash._basevalues@^3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7"
|
resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7"
|
||||||
|
|
||||||
|
lodash._createwrapper@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz#51d6957973da4ed556e37290d8c1a18c53de1607"
|
||||||
|
dependencies:
|
||||||
|
lodash._basebind "~2.4.1"
|
||||||
|
lodash._basecreatewrapper "~2.4.1"
|
||||||
|
lodash._slice "~2.4.1"
|
||||||
|
lodash.isfunction "~2.4.1"
|
||||||
|
|
||||||
lodash._escapehtmlchar@~2.4.1:
|
lodash._escapehtmlchar@~2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d"
|
resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d"
|
||||||
@ -4681,12 +4783,38 @@ lodash._root@^3.0.0:
|
|||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
|
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
|
||||||
|
|
||||||
|
lodash._setbinddata@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz#f7c200cd1b92ef236b399eecf73c648d17aa94d2"
|
||||||
|
dependencies:
|
||||||
|
lodash._isnative "~2.4.1"
|
||||||
|
lodash.noop "~2.4.1"
|
||||||
|
|
||||||
lodash._shimkeys@~2.4.1:
|
lodash._shimkeys@~2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203"
|
resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203"
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash._objecttypes "~2.4.1"
|
lodash._objecttypes "~2.4.1"
|
||||||
|
|
||||||
|
lodash._slice@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._slice/-/lodash._slice-2.4.1.tgz#745cf41a53597b18f688898544405efa2b06d90f"
|
||||||
|
|
||||||
|
lodash.assign@^2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-2.4.1.tgz#84c39596dd71181a97b0652913a7c9675e49b1aa"
|
||||||
|
dependencies:
|
||||||
|
lodash._basecreatecallback "~2.4.1"
|
||||||
|
lodash._objecttypes "~2.4.1"
|
||||||
|
lodash.keys "~2.4.1"
|
||||||
|
|
||||||
|
lodash.bind@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-2.4.1.tgz#5d19fa005c8c4d236faf4742c7b7a1fcabe29267"
|
||||||
|
dependencies:
|
||||||
|
lodash._createwrapper "~2.4.1"
|
||||||
|
lodash._slice "~2.4.1"
|
||||||
|
|
||||||
lodash.cond@^4.3.0:
|
lodash.cond@^4.3.0:
|
||||||
version "4.5.2"
|
version "4.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
|
resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
|
||||||
@ -4724,6 +4852,10 @@ lodash.escape@~2.4.1:
|
|||||||
lodash._reunescapedhtml "~2.4.1"
|
lodash._reunescapedhtml "~2.4.1"
|
||||||
lodash.keys "~2.4.1"
|
lodash.keys "~2.4.1"
|
||||||
|
|
||||||
|
lodash.identity@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.identity/-/lodash.identity-2.4.1.tgz#6694cffa65fef931f7c31ce86c74597cf560f4f1"
|
||||||
|
|
||||||
lodash.isarguments@^3.0.0:
|
lodash.isarguments@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
||||||
@ -4736,6 +4868,10 @@ lodash.isequal@^4.0.0:
|
|||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
|
|
||||||
|
lodash.isfunction@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz#2cfd575c73e498ab57e319b77fa02adef13a94d1"
|
||||||
|
|
||||||
lodash.isobject@~2.4.1:
|
lodash.isobject@~2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5"
|
resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5"
|
||||||
@ -4770,6 +4906,10 @@ lodash.mapvalues@^4.4.0:
|
|||||||
version "4.6.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
|
resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
|
||||||
|
|
||||||
|
lodash.noop@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-2.4.1.tgz#4fb54f816652e5ae10e8f72f717a388c7326538a"
|
||||||
|
|
||||||
lodash.restparam@^3.0.0:
|
lodash.restparam@^3.0.0:
|
||||||
version "3.6.1"
|
version "3.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||||
@ -4778,6 +4918,12 @@ lodash.some@^4.6.0:
|
|||||||
version "4.6.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
|
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
|
||||||
|
|
||||||
|
lodash.support@~2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.support/-/lodash.support-2.4.1.tgz#320e0b67031673c28d7a2bb5d9e0331a45240515"
|
||||||
|
dependencies:
|
||||||
|
lodash._isnative "~2.4.1"
|
||||||
|
|
||||||
lodash.template@^2.4.1:
|
lodash.template@^2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d"
|
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d"
|
||||||
@ -6139,7 +6285,7 @@ read-pkg@^2.0.0:
|
|||||||
normalize-package-data "^2.3.2"
|
normalize-package-data "^2.3.2"
|
||||||
path-type "^2.0.0"
|
path-type "^2.0.0"
|
||||||
|
|
||||||
readable-stream@1.1.x, readable-stream@~1.1.9:
|
readable-stream@1.1.x, readable-stream@^1.0.26-2, readable-stream@^1.0.26-4, readable-stream@~1.1.9:
|
||||||
version "1.1.14"
|
version "1.1.14"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6979,6 +7125,12 @@ streamfilter@^1.0.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
readable-stream "^2.0.2"
|
readable-stream "^2.0.2"
|
||||||
|
|
||||||
|
streamqueue@0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/streamqueue/-/streamqueue-0.0.6.tgz#66f5f5ec94e9b8af249e4aec2dd1f741bfe94de3"
|
||||||
|
dependencies:
|
||||||
|
readable-stream "^1.0.26-2"
|
||||||
|
|
||||||
streamsearch@0.1.2:
|
streamsearch@0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||||
@ -7266,7 +7418,7 @@ through2@^0.5.0:
|
|||||||
readable-stream "~1.0.17"
|
readable-stream "~1.0.17"
|
||||||
xtend "~3.0.0"
|
xtend "~3.0.0"
|
||||||
|
|
||||||
through2@^0.6.0, through2@^0.6.1:
|
through2@^0.6.0, through2@^0.6.1, through2@~0.6.3, through2@~0.6.5:
|
||||||
version "0.6.5"
|
version "0.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
|
resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7280,7 +7432,7 @@ through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0:
|
|||||||
readable-stream "^2.1.5"
|
readable-stream "^2.1.5"
|
||||||
xtend "~4.0.1"
|
xtend "~4.0.1"
|
||||||
|
|
||||||
through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
|
through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1:
|
||||||
version "2.3.8"
|
version "2.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user