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:
committed by
Paulus Schoutsen
parent
7b61826134
commit
29fad98754
+1
-1
@@ -30,7 +30,7 @@ function renamePanel(path) {
|
||||
}
|
||||
}
|
||||
|
||||
gulp.task('build', ['ru_all'], () => {
|
||||
gulp.task('build', ['ru_all', 'build-translations'], () => {
|
||||
const strategy = composeStrategies([
|
||||
generateShellMergeStrategy(polymerConfig.shell),
|
||||
stripImportsStrategy([
|
||||
|
||||
@@ -39,6 +39,7 @@ var staticFingerprinted = [
|
||||
'mdi.html',
|
||||
'core.js',
|
||||
'compatibility.js',
|
||||
'translations/en.json',
|
||||
];
|
||||
|
||||
// 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.
|
||||
staticFingerprinted.forEach(fn => {
|
||||
var parts = path.parse(fn);
|
||||
var hash = md5(rootDir + '/' + parts.name + parts.ext);
|
||||
var url = '/static/' + parts.name + '-' + hash + parts.ext;
|
||||
var fpath = rootDir + '/' + parts.name + parts.ext;
|
||||
var base = parts.dir.length > 0 ? parts.dir + '/' + parts.name : parts.name;
|
||||
var hash = md5(rootDir + '/' + base + parts.ext);
|
||||
var url = '/static/' + base + '-' + hash + parts.ext;
|
||||
var fpath = rootDir + '/' + base + parts.ext;
|
||||
dynamicUrlToDependencies[url] = [fpath];
|
||||
});
|
||||
|
||||
@@ -89,6 +91,10 @@ gulp.task('gen-service-worker', () => {
|
||||
rootDir + '/fonts/roboto/Roboto-Bold.ttf',
|
||||
rootDir + '/images/card_media_player_bg.png',
|
||||
],
|
||||
runtimeCaching: [{
|
||||
urlPattern: /\/static\/translations\//,
|
||||
handler: 'cacheFirst',
|
||||
}],
|
||||
stripPrefix: 'hass_frontend',
|
||||
replacePrefix: 'static',
|
||||
verbose: true,
|
||||
|
||||
Executable
+111
@@ -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;
|
||||
Reference in New Issue
Block a user