{"id":17965367,"url":"https://github.com/t2ym/live-localizer","last_synced_at":"2025-03-25T07:31:07.996Z","repository":{"id":48279342,"uuid":"63053056","full_name":"t2ym/live-localizer","owner":"t2ym","description":"Live Localizer widget for lit-html and Polymer","archived":false,"fork":false,"pushed_at":"2022-05-23T20:15:00.000Z","size":27197,"stargazers_count":6,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-08T21:48:05.146Z","etag":null,"topics":["cloud-storage","firebase","i18n","polymer","translation","xliff"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/t2ym.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-11T09:03:12.000Z","updated_at":"2021-09-29T07:47:38.000Z","dependencies_parsed_at":"2022-08-19T03:00:28.878Z","dependency_job_id":null,"html_url":"https://github.com/t2ym/live-localizer","commit_stats":null,"previous_names":[],"tags_count":144,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Flive-localizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Flive-localizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Flive-localizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Flive-localizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/t2ym","download_url":"https://codeload.github.com/t2ym/live-localizer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222047618,"owners_count":16922198,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloud-storage","firebase","i18n","polymer","translation","xliff"],"created_at":"2024-10-29T12:42:02.418Z","updated_at":"2024-10-29T12:42:02.982Z","avatar_url":"https://github.com/t2ym.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/t2ym/live-localizer.svg?branch=master)](https://travis-ci.org/t2ym/live-localizer)\n[![Coverage Status](https://coveralls.io/repos/github/t2ym/live-localizer/badge.svg?branch=master)](https://coveralls.io/github/t2ym/live-localizer?branch=master)\n[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/t2ym/live-localizer)\n[![npm](https://img.shields.io/npm/v/live-localizer.svg)](https://www.npmjs.com/package/live-localizer)\n\n# Live Localizer\n\nLive Localizer widget for [Lit](https://lit.dev/) and [i18n-element](https://www.webcomponents.org/element/t2ym/i18n-element)\n\n[Live Demo](https://www.webcomponents.org/element/t2ym/live-localizer/demo/demo/index.html) on [webcomponents.org](https://www.webcomponents.org/element/t2ym/live-localizer)\n\n## Live Localizer applied to [the Shop App](https://www.polymer-project.org/1.0/toolbox/case-study)\n\n\u003cimg src=\"https://raw.githubusercontent.com/wiki/t2ym/live-localizer/live-localizer.gif\" width=\"768px\"\u003e\n\n#### Sequential description of the animated screenshot above\n\n- Browse the Shop App with Live Localizer widget at the bottom left corner as a fab icon\n- Open the Live Localizer widget\n- Switch to the Japanese locale with pseudo-L10N\n- Save the working strings of the Shop App as a local XLIFF file `bundle.ja.xlf`\n- Open the local XLIFF with XLIFF editor [Virtaal](https://github.com/translate/virtaal) \n- Translate the local XLIFF (Actually, open the translated XLIFF `shop-bundle.ja.xlf`)\n- Drag and drop the translated XLIFF from Windows Explorer to Live Localizer widget\n- Load the dropped XLIFF to the running Shop App\n- Browse the localized Shop App\n- Switch to the English locale\n\n## Table of Contents\n\n- [Use Cases](#use-cases)\n- [Features](#features)\n- [Supported Browsers](#supported-browsers)\n- [Install](#install)\n- [Import](#import)\n- [Apply](#apply)\n- [Firebase Setup (Optional)](#firebase-setup-optional)\n- [Local XLIFF Watcher (Optional)](#local-xliff-watcher-optional)\n- [Build](#build)\n- [Plans](#plans)\n- [License](#license)\n\n## Use Cases\n\n- Dispatch translation tasks via the running Web app itself\n- Dispatch incremental translation tasks via the running Web app itself\n- Check screenshots on the running Web app\n- Check translation progress in statistics view\n- Submit translations to Cloud (Firebase)\n- Watch Cloud to update translations in real-time\n\n## Features\n\n- Export XLIFF from the running app to a local file\n- Import XLIFF from a local file to the running app\n- Save XLIFF to Browser Storage (IndexedDB)\n- Load XLIFF from Browser Storage (IndexedDB)\n- Upload XLIFF to Cloud Storate (Firebase)\n- Download XLIFF from Cloud Storage (Firebase)\n- Show translation statistics in list view\n- Detect changes on Cloud Storage (Firebase) to trigger a new build\n- Detect changes and load Local XLIFF \n\n## Supported Browsers\n\n| Browsers | Supported Versions  | Platforms                                  |\n|:--------:|:-------------------:|:------------------------------------------:|\n| Chrome   | 59+                 | Windows 7+, macOS El Capitan 10.11+, Linux |\n| Firefox  | 54+                 | Windows 7+, macOS El Capitan 10.11+, Linux |\n| Safari   | 10.1.1 (12603.2.4)+ | macOS Sierra 10.12+                        |\n\n## Install\n\n```sh\n  npm install live-localizer\n```\n\n## Import\n\n### Static Loading\n```html\n  \u003cscript src=\"/node_modules/web-animations-js/web-animations-next.min.js\"\u003e\u003c/script\u003e\u003c!-- required for live-localizer --\u003e\n  \u003cscript type=\"module\" src=\"live-localizer/live-localizer.js\"\u003e\u003c/script\u003e\n```\n\n### Lazy Loading\n```html\n  \u003cscript src=\"/node_modules/web-animations-js/web-animations-next.min.js\"\u003e\u003c/script\u003e\u003c!-- required for live-localizer --\u003e\n  \u003cscript type=\"module\" src=\"live-localizer/live-localizer-lazy.js\"\u003e\u003c/script\u003e\n```\n\n## Apply\n\nAttach at the end of the main body element.\n\n### With Firebase Cloud Storage:\n\n```html\n\u003cbody\u003e\n  ...\n  \u003clive-localizer\u003e\n    \u003c!--\n      Firebase Cloud Storage configuration with the example parameters for Live Localizer demo app:\n      For each target app, a dedicated Firebase project has to be configured.\n    --\u003e\n    \u003clive-localizer-firebase-storage id=\"firebase-storage\" class=\"storage cloud\"\n      auth-provider=\"google\"\n      auth-domain=\"live-localizer-demo.firebaseapp.com\"\n      database-url=\"https://live-localizer-demo.firebaseio.com\"\n      api-key=\"AIzaSyCjrlPhl0cLSZVRsDvuajq16vkerhcu_UM\"\u003e\n    \u003c/live-localizer-firebase-storage\u003e\n  \u003c/live-localizer\u003e\n\u003c/body\u003e\n```\n\n### Without Firebase Cloud Storage:\n\n```html\n\u003cbody\u003e\n  ...\n  \u003clive-localizer\u003e\u003c/live-localizer\u003e\n\u003c/body\u003e\n```\n\n## Firebase Setup (Optional)\n\nA dedicated Firebase project has to be set up for storing XLIFF files for the target application.\n\n### Supported Authentication Methods\n\n- Anonymous\n- Google (OAuth)\n- GitHub (OAuth)\n- Twitter (OAuth)\n\n### Firebase Security Rules\n\n```javascript\n{\n  \"rules\": {\n    \"users\": {\n      \".read\": \"auth.uid === 'xliff-watcher'\",\n      \"$uid\": {\n        \".read\": \"$uid === auth.uid\",\n        \".write\": \"$uid === auth.uid\"\n      }\n    }\n  }\n}\n```\n\n### XLIFF Watcher (Optional)\n\nXLIFF Watcher in the build system can detect XLIFF file changes in Firebase in realtime and trigger a new build.\n\nSee `gulp fetch-xliff` and `gulp watch-xliff` tasks in [`demo/gulpfile.js`](https://github.com/t2ym/live-localizer/blob/master/demo/gulpfile.js)\n\n#### Start Watching:\n\n```sh\n  gulp watch-xliff --database https://live-localizer-demo.firebaseio.com \\\n    --service_account ../../live-localizer-demo-service-account.json \\\n    --on_xliff_change 'npm run fetch-xliff \u0026\u0026 npm run demo' \\\n    \u003e../../logfile.txt 2\u003e\u00261 \u0026\n  tail -f ../../logfile.txt\n```\n\nExample XLIFF Watcher processes:\n```sh\n$ gulp watch-xliff --database https://live-localizer-demo.firebaseio.com \\\n\u003e     --service_account ../../live-localizer-demo-service-account.json \\\n\u003e     --on_xliff_change 'npm run fetch-xliff \u0026\u0026 npm run demo' # fetch-xliff options have to be configured\n[10:03:02] Using gulpfile ~/WebComponents/components/live-localizer/demo/gulpfile.js\n[10:03:02] Starting 'watch-xliff'...\n[10:03:02] watch-xliff: Watching changes on Firebase...\n[10:03:02] watch-xliff: gulp unwatch-xliff to stop the task\nThe 'credential' property specified in the first argument to initializeApp() is deprecated and will be removed in the next major version. You should instead use the 'firebase-admin' package. See https://firebase.google.com/docs/admin/setup for details on how to get started.\n[10:04:08] watch-xliff: Change detected on Firebase\n[10:04:08] watch-xliff: Executing: npm run demo\n[10:04:17] \n\u003e live-localizer@0.0.79 demo /home/fedora/WebComponents/components/live-localizer\n\u003e cd demo \u0026\u0026 gulp\n\n[10:04:09] Using gulpfile ~/WebComponents/components/live-localizer/demo/gulpfile.js\n[10:04:09] Starting 'default'...\n[10:04:09] Starting 'fetch-xliff'...\n[10:04:16] By All Users:\n[10:04:16] 01i7iz6EbGcYTWemYAHlgrIb7fl1.files.de date: 2017-06-13T12:11:10Z\n...\n[10:04:16] zsZzpSw2rNXV0YNfd0xo42L5kpL2.files.ja date: 2017-05-25T05:43:19Z\n[10:04:16] By All Users in reverse chronological order:\n[10:04:16] files[de][0] user: nU3pjXUSyMbn6hScNe7I2unkbOf1 date: 2017-06-22T11:32:17Z \u003c= selected\n...\n[10:04:16] files[de][507] user: QFCCp3HqHCZjCaMldd95R3d5Ck12 date: 2017-02-11T15:37:19Z\n[10:04:16] files[ja][0] user: YCogwiL4MKQ76fwcXXi6vlJljxG2 date: 2017-06-23T01:04:08Z \u003c= selected\n...\n[10:04:16] files[ja][76] user: NUPdA2ijDFV3qSogo8VkTSfcFRx2 date: 2016-08-03T09:06:59Z\n[10:04:16] files[zh-Hans][0] user: fPgOtPel47c4yjM35roNoGqw1vE2 date: 2016-08-03T09:48:28Z \u003c= selected\n[10:04:16] files[fr][0] user: v8Ny5UnVZpQw3aGcoKpNq3kkVv22 date: 2017-06-07T07:44:05Z \u003c= selected\n[10:04:16] Finished 'fetch-xliff' after 6.77 s\n[10:04:16] Starting 'i18n'...\n[10:04:16] I18N transform index.html\n...\n[10:04:16] I18N transform locales/bundle.de.json\n[10:04:16] I18N transform bundle.json\n[10:04:16] I18N transform locales/bundle.es.json\n[10:04:16] I18N transform locales/bundle.fr.json\n[10:04:16] I18N transform locales/bundle.ja.json\n[10:04:16] I18N transform locales/bundle.zh-Hans.json\n[10:04:16] I18N transform xliff/bundle.de.xlf\n[10:04:16] I18N transform xliff/bundle.es.xlf\n[10:04:16] I18N transform xliff/bundle.fr.xlf\n[10:04:16] I18N transform xliff/bundle.ja.xlf\n[10:04:16] I18N transform xliff/bundle.zh-Hans.xlf\n[10:04:16] I18N transform 40 items\n[10:04:16] Finished 'i18n' after 375 ms\n[10:04:16] Finished 'default' after 7.15 s\n\n[10:04:17] watch-xliff: The task on the XLIFF changes has finished. Continuing to watch changes on Firebase...\n[10:04:48] Finished 'watch-xliff' after 1.75 min\n[10:04:48] watch-xliff: stop watching xliff\n```\n\n#### Stop Watching:\n\n```sh\n  gulp unwatch-xliff\n```\n\n#### Notes on XLIFF Watcher:\n\n- Service account credentials' JSON is required for `gulp watch-xliff` task\n- `--token=notoken` option to use the same service account credentials for `gulp fetch-xliff` task as `gulp watch-xliff` task\n  - `demo/getUsers.js` script, which uses `firebase-admin` SDK, is required to use the credentials\n- Otherwise, `firebase login:ci` token from `firebase-tools` is required for `gulp fetch-xliff` task\n\n## Local XLIFF Watcher (Optional)\n\nLocal XLIFF file changes can be watched real-time via local HTTP server at http://localhost:8887/UPLOADED_XLIFF_FILE\n\nCheck \"Watch and Load XLIFF\" in the local file storage control panel to start watching the local XLIFF file\n\nThe following table shows triggered operations whenever the translator saves (overwrites) the local XLIFF file\n\n| Components | Operations |\n|:-----------|:-----------|\n| XLIFF Editor | Save (overwrite) the uploaded XLIFF file |\n| `http-server` | Provide Local XLIFF Watcher with the XLIFF file status |\n| Local XLIFF Watcher in Live Localizer | Periodically check the XLIFF file status and fetch it on its updates |\n| `xliff-conv` in Live Localizer | Merge the XLIFF updates into the JSON data for running UI strings |\n| Target Application | Show UI with the updated strings |\n| Browser Storage | Automatically save the XLIFF file if \"Automatic Save\" is checked |\n| Firebase Storage | Automatically upload the XLIFF file if \"Automatic Save\" is checked |\n| Firebase | Notify XLIFF Watcher of a `child_changed` event for the XLIFF file updates |\n| XLIFF Watcher (`watch-xliff` gulp task) in the build system | Detect the `child_changed` event and trigger a new build |\n| Build system | Start a new build process including `fetch-xliff` gulp task and I18N, and deploy a new build on the development HTTP server |\n| Development HTTP server | Provide browsers for translators with the new build |\n| Reload button in Live Localizer | Detect the new build in 60 seconds and show the tooltip \"App Updated\" |\n\n### HTTP Server for Local XLIFF Watcher Setup\n\n- Install [NodeJS](https://nodejs.org/) on the local host of the translator\n- Install [the local HTTP server npm package](https://www.npmjs.com/package/http-server)\n```sh\nnpm install -g http-server\n```\n- For HTTP sites, start local HTTP server at http://localhost:8887 with the root folder containing the XLIFF file\n```sh\nhttp-server FOLDER_TO_CONTAIN_XLIFF -d false -c-1 -r -a localhost -p 8887 --cors=If-Modified-Since\n```\n- For HTTPS sites, start local HTTPS server at https://localhost:8887 with the root folder containing the XLIFF file\n\nBatch File to Launch local HTTPS server on Windows from Node.js command prompt: [`https-local-server.bat`](https://github.com/t2ym/live-localizer/blob/master/http-local-server.zip?raw=true) FOLDER_TO_CONTAIN_XLIFF\n```\n@echo off\nif \"%1\"==\"\" echo Please specify the path to the root folder containing the target XLIFF file\nif \"%1\"==\"\" echo %0 C:\\Path\\To\\XLIFF\\Folder\nif \"%1\"==\"\" goto :end\nif exist C:\\OpenSSL-Win64 set OPENSSL_CONF=C:\\OpenSSL-Win64\\bin\\openssl.cfg\nif exist C:\\OpenSSL-Win64 set PATH=%PATH%;C:\\OpenSSL-Win64\\bin\nif exist C:\\OpenSSL-Win32 set OPENSSL_CONF=C:\\OpenSSL-Win32\\bin\\openssl.cfg\nif exist C:\\OpenSSL-Win32 set PATH=%PATH%;C:\\OpenSSL-Win32\\bin\nif \"%OPENSSL_CONF%\"==\"\" echo Please install OpenSSL package for Windows from https://slproweb.com/products/Win32OpenSSL.html linked from https://wiki.openssl.org/index.php/Binaries\nif \"%OPENSSL_CONF%\"==\"\" goto :end\nif not exist demoCA mkdir demoCA\ncd demoCA\nif not exist newcerts mkdir newcerts\ntype nul \u003eindex.txt\necho 01 \u003eserial\nif not exist localhostCA.key openssl genrsa 2048 \u003elocalhostCA.key\nif not exist localhostCA.csr openssl req -new -key localhostCA.key -subj \"/C=JP/ST=Tokyo/O=i18n-behavior/OU=Live Localizer/CN=Live Localizer Localhost CA\" -out localhostCA.csr\ndel /Q CAcreation\nif not exist localhostCA.crt type nul \u003eCAcreation\nif not exist localhostCA.crt openssl x509 -days 3650 -sha256 -req -signkey localhostCA.key -in localhostCA.csr -out localhostCA.crt\nif not exist localhost.key openssl genrsa 2048 \u003elocalhost.key\nif exist localhost_csr.txt goto :csr\necho [req] \u003elocalhost_csr.txt\necho default_bits = 2048 \u003e\u003elocalhost_csr.txt\necho prompt = no \u003e\u003elocalhost_csr.txt\necho default_md = sha256 \u003e\u003elocalhost_csr.txt\necho req_extensions = SAN \u003e\u003elocalhost_csr.txt\necho distinguished_name = dn \u003e\u003elocalhost_csr.txt\necho [dn] \u003e\u003elocalhost_csr.txt\necho C=JP \u003e\u003elocalhost_csr.txt\necho ST=Tokyo \u003e\u003elocalhost_csr.txt\necho O=i18n-behavior \u003e\u003elocalhost_csr.txt\necho OU=Live Localizer \u003e\u003elocalhost_csr.txt\necho CN=localhost \u003e\u003elocalhost_csr.txt\necho [SAN] \u003e\u003elocalhost_csr.txt\necho subjectAltName=DNS:localhost \u003e\u003elocalhost_csr.txt\n:csr\nif not exist localhost.csr openssl req -config localhost_csr.txt -new -sha256 -key localhost.key -out localhost.csr\nopenssl req -text -noout -in localhost.csr\ncd ..\nif not exist demoCA\\localhost.crt openssl x509 -req -CA demoCA\\localhostCA.crt -CAkey demoCA\\localhostCA.key -CAcreateserial -out demoCA\\localhost.crt -in demoCA\\localhost.csr -sha256 -days 3650 -extfile demoCA\\localhost_csr.txt -extensions SAN\nif exist demoCA\\CAcreation echo Please install the generated Localhost CA certificate as \"Trusted Root Certification Authorities\"\nif exist demoCA\\CAcreation demoCA\\localhostCA.crt\necho http-server \"%1\" -d false -c-1 -r -a localhost -p 8887 --cors=If-Modified-Since --ssl --cert demoCA\\localhost.crt --key demoCA\\localhost.key\nhttp-server \"%1\" -d false -c-1 -r -a localhost -p 8887 --cors=If-Modified-Since --ssl --cert demoCA\\localhost.crt --key demoCA\\localhost.key\n:end\n```\n\nScript to Launch local HTTPS server on Mac: [`https-local-server.sh`](https://gist.githubusercontent.com/t2ym/b633f6a92e72e64e03ab8ad53e14e912/raw/096fda8f229b64f5b6c9dfde64bd9ca1870d6608/https-local-server.sh) FOLDER_TO_CONTAIN_XLIFF\n```sh\n#!/bin/sh\n\nif [ \"$1\" = \"\" ]; then\n  echo Please specify the path to the root folder containing the target XLIFF file\n  echo $0 /Path/To/XLIFF/Folder\n  exit 1\nfi\nwhich openssl\nif [ \"$?\" = \"1\" ]; then\n  echo Please install openssl command\n  exit 1\nfi\nmkdir -p demoCA\ncd demoCA\nmkdir -p newcerts\nrm -f index.txt\ntouch index.txt\necho 01 \u003eserial\nif [ ! -e localhostCA.key ]; then\n  openssl genrsa 2048 \u003elocalhostCA.key\nfi\nif [ ! -e localhostCA.csr ]; then\n  openssl req -new -key localhostCA.key -subj \"/C=JP/ST=Tokyo/O=i18n-behavior/OU=Live Localizer/CN=Live Localizer Localhost CA\" -out localhostCA.csr\nfi\nrm -f CAcreation\nif [ ! -e localhostCA.crt ]; then\n  touch CAcreation\n  openssl x509 -days 3650 -sha256 -req -signkey localhostCA.key -in localhostCA.csr -out localhostCA.crt\nfi\nif [ ! -e localhost.key ]; then\n  openssl genrsa 2048 \u003elocalhost.key\nfi\nif [ ! -e localhost.csr ]; then\ncat \u003e localhost_csr.txt \u003c\u003c-EOF\n[req]\ndefault_bits = 2048\nprompt = no\ndefault_md = sha256\nreq_extensions = SAN\ndistinguished_name = dn\n\n[dn]\nC=JP\nST=Tokyo\nO=i18n-behavior\nOU=Live Localizer\nCN=localhost\n\n[SAN]\nsubjectAltName=DNS:localhost\nEOF\n  openssl req -config localhost_csr.txt -new -sha256 -key localhost.key -out localhost.csr\n  openssl req -text -noout -in localhost.csr\nfi\ncd ..\nif [ ! -e demoCA/localhost.crt ]; then\n  openssl x509 -req -CA demoCA/localhostCA.crt -CAkey demoCA/localhostCA.key -CAcreateserial -out demoCA/localhost.crt -in demoCA/localhost.csr -sha256 -days 3650 \\\n  -extfile demoCA/localhost_csr.txt -extensions SAN\nfi\nif [ -e demoCA/CAcreation ]; then\n  echo Please install the generated Localhost CA certificate demoCA/localhostCA.crt as Trusted Certificate for SSL\n  if [ \"`uname`\" = \"Darwin\" ]; then\n    open demoCA/localhostCA.crt\n  fi\nfi\necho http-server \"$1\" -d false -c-1 -r -a localhost -p 8887 --cors=If-Modified-Since --ssl --cert demoCA/localhost.crt --key demoCA/localhost.key\nhttp-server \"$1\" -d false -c-1 -r -a localhost -p 8887 --cors=If-Modified-Since --ssl --cert demoCA/localhost.crt --key demoCA/localhost.key\n```\n\n#### Notes on Local XLIFF Watcher:\n- The XLIFF folder should contain only the target XLIFF file(s) for the project for security.\n- The HTTP server is accessible only from the localhost and disallows directory listing.\n- If the XLIFF file name is prefixed with an unpredictable string, it can serve as a kind of \"password\" to block malicious access from other local HTTP clients.\n- `https-local-server` script has to be executed in the same folder as its first execution so that it can find the generated certificates in `./demoCA` folder.\n- To work around [Issue #76](https://github.com/t2ym/live-localizer/issues/76), `https-local-server` script is required even for HTTP web applications.\n\n## Build\n\n### Bundle dependent components with `polymer-build` bundler\n\nWith lazy loader `live-localizer-lazy.js`, `live-localizer-main.js` and its dependencies are lazily loaded.\nThe dependent components except for region flag images can be bundled with `polymer-build` bundler as follows.\n\n#### `polymer.json` with bundled `live-localizer` dependencies: applied to [I18n-ready `pwa-starter-kit`](https://github.com/t2ym/pwa-starter-kit)\n```json\n{\n  \"entrypoint\": \"index.html\",\n  \"shell\": \"preprocess/components/my-app.js\",\n  \"sources\": [\n    \"images/**/*\",\n    \"preprocess/**/locales/**\",\n    \"preprocess/bundle.json\"\n  ],\n  \"fragments\": [\n    \"node_modules/live-localizer/live-localizer-main.js\"\n  ],\n  \"extraDependencies\": [\n    \"manifest.json\",\n    \"node_modules/@webcomponents/webcomponentsjs/**\",\n    \"node_modules/web-animations-js/web-animations-next.min.js\",\n    \"node_modules/region-flags/png/**\",\n    \"push-manifest.json\"\n  ],\n  \"builds\": [\n    {\n      \"name\": \"esm-bundled\",\n      \"browserCapabilities\": [\n        \"es2015\",\n        \"modules\"\n      ],\n      \"js\": {\n        \"minify\": true\n      },\n      \"css\": {\n        \"minify\": true\n      },\n      \"html\": {\n        \"minify\": true\n      },\n      \"bundle\": true,\n      \"addServiceWorker\": true\n    }\n  ],\n  \"moduleResolution\": \"node\",\n  \"npm\": true\n}\n```\n\n#### `live-localizer-lazy.js` has to be imported from the main shell to be bundled properly\n\n```diff\ndiff --git a/src/components/my-app.js b/src/components/my-app.js\nindex bc4a154..69f43ba 100644\n--- a/src/components/my-app.js\n+++ b/src/components/my-app.js\n@@ -35,6 +35,8 @@ import '@polymer/app-layout/app-toolbar/app-toolbar.js';\n import { menuIcon } from './my-icons.js';\n import './snack-bar.js';\n \n+import 'live-localizer/live-localizer-lazy.js';\n+\n class MyApp extends connect(store)(i18n(LitElement)) {\n   static get importMeta() {\n     return import.meta;\ndiff --git a/preprocess/components/my-app.js b/preprocess/components/my-app.js\nindex 54a1f03..0dbd10c 100644\n--- a/preprocess/components/my-app.js\n+++ b/preprocess/components/my-app.js\n@@ -34,6 +34,7 @@ import '@polymer/app-layout/app-scroll-effects/effects/waterfall.js';\n import '@polymer/app-layout/app-toolbar/app-toolbar.js';\n import { menuIcon } from './my-icons.js';\n import './snack-bar.js';\n+import 'live-localizer/live-localizer-lazy.js';\n class MyApp extends connect(store)(i18n(LitElement)) {\n   static get importMeta() {\n     return import.meta;\n```\n\n## Plans\n\nTBD\n\n## License\n\n[BSD-2-Clause](https://github.com/t2ym/live-localizer/blob/master/LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft2ym%2Flive-localizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ft2ym%2Flive-localizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft2ym%2Flive-localizer/lists"}