Add lit components localization

Localization is performed via the @lit/localize package, which has been
integrated into the repo. A I18nLitElement class which extends
LitElement has been included, which automatically sets up the
localization.

This CL also introduces localization to the flattenThreads feature.

Fixed: twpowertools:157
Change-Id: If01540b9c8d70876a648aa002a1e0a5bede8f383
diff --git a/Makefile b/Makefile
index bef8a1c..7cb4294 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: node_deps clean_dist deps clean_deps serve_chromium serve_chromium_mv3 serve_gecko release release_chromium_stable release_chromium_beta release_chromium_canary release_gecko_stable build_test_extension clean_releases test clean trigger_nightly_build
+.PHONY: node_deps clean_dist deps clean_deps lit_localize_extract lit_localize_build lit_localize_all serve_chromium serve_chromium_mv3 serve_gecko release release_chromium_stable release_chromium_beta release_chromium_canary release_gecko_stable build_test_extension clean_releases test clean trigger_nightly_build
 
 WEBPACK := ./node_modules/webpack-cli/bin/cli.js
 JEST := node --experimental-vm-modules ./node_modules/jest/bin/jest.js
@@ -23,6 +23,14 @@
 clean_deps:
 	rm -rf node_modules
 
+lit_localize_extract:
+	npx lit-localize extract
+
+lit_localize_build:
+	npx lit-localize build
+
+lit_localize_all: lit_localize_extract lit_localize_build
+
 serve_chromium: deps
 	$(WEBPACK) --mode development --env browser_target=chromium --watch
 
diff --git a/i18n-config.toml b/i18n-config.toml
index 8c02374..dd55467 100644
--- a/i18n-config.toml
+++ b/i18n-config.toml
@@ -1,11 +1,22 @@
 base_path = "."
 
+# NOTE: Keep in sync with lit-localize.json
 locales = [
+  "ar",
   "ca",
+  "de",
   "es",
-  "ru",
+  "fr",
+  "id",
+  "it",
+  "ja",
+  "ko",
+  "pl",
   "pt_BR",
-  "pt_PT",
+  "ru",
+  "th",
+  "tr",
+  "vi",
 ]
 
 branches = [
@@ -19,3 +30,6 @@
 [[paths]]
   reference = "cws/en/listing-description.lang"
   l10n = "cws/{android_locale}/listing-description.lang"
+
+[[paths]]
+  l10n = "src/lit-locales/source/{android_locale}.xlf"
diff --git a/lit-localize.json b/lit-localize.json
new file mode 100644
index 0000000..1bbc7a7
--- /dev/null
+++ b/lit-localize.json
@@ -0,0 +1,36 @@
+{
+  "$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
+  "sourceLocale": "en",
+  "targetLocales": [
+    "ar",
+    "ca",
+    "de",
+    "es",
+    "fr",
+    "id",
+    "it",
+    "ja",
+    "ko",
+    "pl",
+    "pt_BR",
+    "ru",
+    "th",
+    "tr",
+    "vi"
+  ],
+  "inputFiles": [
+    "src/contentScripts/communityConsole/flattenThreads/components/**/*.js",
+    "src/contentScripts/communityConsole/workflows/components/**/*.js",
+    "src/contentScripts/communityConsole/threadToolbar/components/**/*.js",
+    "src/workflows/manager/components/**/*.js"
+  ],
+  "output": {
+    "mode": "runtime",
+    "outputDir": "./src/lit-locales/generated",
+    "localeCodesModule": "./src/lit-locales/generated/locales.js"
+  },
+  "interchange": {
+    "format": "xliff",
+    "xliffDir": "./src/lit-locales/source"
+  }
+}
diff --git a/package-lock.json b/package-lock.json
index 63a33fb..ea10113 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
       "version": "0.0.0",
       "license": "MIT",
       "dependencies": {
+        "@lit/localize": "^0.11.4",
         "@material/mwc-circular-progress": "^0.27.0",
         "@material/mwc-dialog": "^0.27.0",
         "@material/tooltip": "^12.0.0",
@@ -25,6 +26,7 @@
       },
       "devDependencies": {
         "@babel/plugin-transform-modules-commonjs": "^7.20.11",
+        "@lit/localize-tools": "^0.6.7",
         "copy-webpack-plugin": "^9.0.1",
         "css-loader": "^6.2.0",
         "eslint": "^8.30.0",
@@ -1148,10 +1150,54 @@
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "node_modules/@lit-labs/ssr-dom-shim": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.0.0.tgz",
+      "integrity": "sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw=="
+    },
+    "node_modules/@lit/localize": {
+      "version": "0.11.4",
+      "resolved": "https://registry.npmjs.org/@lit/localize/-/localize-0.11.4.tgz",
+      "integrity": "sha512-RRIwIX2tAm3+DuEndoXSJrFjGrAK5cb5IXo5K6jcJ6sbgD829B8rSqHC5MaKVUmXTVLIR1bk5IZOZDf9wFereA==",
+      "dependencies": {
+        "@lit/reactive-element": "^1.4.0",
+        "lit": "^2.3.0"
+      }
+    },
+    "node_modules/@lit/localize-tools": {
+      "version": "0.6.7",
+      "resolved": "https://registry.npmjs.org/@lit/localize-tools/-/localize-tools-0.6.7.tgz",
+      "integrity": "sha512-zzDSuBcO/vWjpGDuKX1SdOkmR2hjNWHmE6XQHLAh21xNEhCiHyN4k5NqN/uPkB2mx7wxK3n6KH3hppN3AANWmA==",
+      "dev": true,
+      "dependencies": {
+        "@lit/localize": "^0.11.0",
+        "@xmldom/xmldom": "^0.8.2",
+        "fast-glob": "^3.2.7",
+        "fs-extra": "^10.0.0",
+        "jsonschema": "^1.4.0",
+        "lit": "^2.6.0",
+        "minimist": "^1.2.5",
+        "parse5": "^6.0.1",
+        "source-map-support": "^0.5.19",
+        "typescript": "~4.7.4"
+      },
+      "bin": {
+        "lit-localize": "bin/lit-localize.js"
+      }
+    },
+    "node_modules/@lit/localize-tools/node_modules/parse5": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+      "dev": true
+    },
     "node_modules/@lit/reactive-element": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz",
-      "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw=="
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz",
+      "integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==",
+      "dependencies": {
+        "@lit-labs/ssr-dom-shim": "^1.0.0"
+      }
     },
     "node_modules/@material/animation": {
       "version": "12.0.0",
@@ -2404,6 +2450,15 @@
         }
       }
     },
+    "node_modules/@xmldom/xmldom": {
+      "version": "0.8.6",
+      "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
+      "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/@xtuc/ieee754": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -3884,6 +3939,29 @@
         "node": ">= 6"
       }
     },
+    "node_modules/fs-extra": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/fs-extra/node_modules/universalify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
     "node_modules/fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -5178,6 +5256,36 @@
         "node": ">=6"
       }
     },
+    "node_modules/jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dev": true,
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/jsonfile/node_modules/universalify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/jsonschema": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
+      "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -5234,13 +5342,13 @@
       "dev": true
     },
     "node_modules/lit": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/lit/-/lit-2.3.1.tgz",
-      "integrity": "sha512-TejktDR4mqG3qB32Y8Lm5Lye3c8SUehqz7qRsxe1PqGYL6me2Ef+jeQAEqh20BnnGncv4Yxy2njEIT0kzK1WCw==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/lit/-/lit-2.6.1.tgz",
+      "integrity": "sha512-DT87LD64f8acR7uVp7kZfhLRrHkfC/N4BVzAtnw9Yg8087mbBJ//qedwdwX0kzDbxgPccWRW6mFwGbRQIxy0pw==",
       "dependencies": {
-        "@lit/reactive-element": "^1.4.0",
+        "@lit/reactive-element": "^1.6.0",
         "lit-element": "^3.2.0",
-        "lit-html": "^2.3.0"
+        "lit-html": "^2.6.0"
       }
     },
     "node_modules/lit-element": {
@@ -5253,9 +5361,9 @@
       }
     },
     "node_modules/lit-html": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.3.1.tgz",
-      "integrity": "sha512-FyKH6LTW6aBdkfNhNSHyZTnLgJSTe5hMk7HFtc/+DcN1w74C215q8B+Cfxc2OuIEpBNcEKxgF64qL8as30FDHA==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz",
+      "integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==",
       "dependencies": {
         "@types/trusted-types": "^2.0.2"
       }
@@ -5415,6 +5523,15 @@
         "node": "*"
       }
     },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -6602,6 +6719,19 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/typescript": {
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
     "node_modules/universalify": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
@@ -7934,10 +8064,53 @@
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "@lit-labs/ssr-dom-shim": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.0.0.tgz",
+      "integrity": "sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw=="
+    },
+    "@lit/localize": {
+      "version": "0.11.4",
+      "resolved": "https://registry.npmjs.org/@lit/localize/-/localize-0.11.4.tgz",
+      "integrity": "sha512-RRIwIX2tAm3+DuEndoXSJrFjGrAK5cb5IXo5K6jcJ6sbgD829B8rSqHC5MaKVUmXTVLIR1bk5IZOZDf9wFereA==",
+      "requires": {
+        "@lit/reactive-element": "^1.4.0",
+        "lit": "^2.3.0"
+      }
+    },
+    "@lit/localize-tools": {
+      "version": "0.6.7",
+      "resolved": "https://registry.npmjs.org/@lit/localize-tools/-/localize-tools-0.6.7.tgz",
+      "integrity": "sha512-zzDSuBcO/vWjpGDuKX1SdOkmR2hjNWHmE6XQHLAh21xNEhCiHyN4k5NqN/uPkB2mx7wxK3n6KH3hppN3AANWmA==",
+      "dev": true,
+      "requires": {
+        "@lit/localize": "^0.11.0",
+        "@xmldom/xmldom": "^0.8.2",
+        "fast-glob": "^3.2.7",
+        "fs-extra": "^10.0.0",
+        "jsonschema": "^1.4.0",
+        "lit": "^2.6.0",
+        "minimist": "^1.2.5",
+        "parse5": "^6.0.1",
+        "source-map-support": "^0.5.19",
+        "typescript": "~4.7.4"
+      },
+      "dependencies": {
+        "parse5": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+          "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+          "dev": true
+        }
+      }
+    },
     "@lit/reactive-element": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz",
-      "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw=="
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz",
+      "integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==",
+      "requires": {
+        "@lit-labs/ssr-dom-shim": "^1.0.0"
+      }
     },
     "@material/animation": {
       "version": "12.0.0",
@@ -9189,6 +9362,12 @@
       "dev": true,
       "requires": {}
     },
+    "@xmldom/xmldom": {
+      "version": "0.8.6",
+      "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
+      "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==",
+      "dev": true
+    },
     "@xtuc/ieee754": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -10293,6 +10472,25 @@
         "mime-types": "^2.1.12"
       }
     },
+    "fs-extra": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "dependencies": {
+        "universalify": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+          "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+          "dev": true
+        }
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -11278,6 +11476,30 @@
       "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
       "dev": true
     },
+    "jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.6",
+        "universalify": "^2.0.0"
+      },
+      "dependencies": {
+        "universalify": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+          "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+          "dev": true
+        }
+      }
+    },
+    "jsonschema": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
+      "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
+      "dev": true
+    },
     "kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -11319,13 +11541,13 @@
       "dev": true
     },
     "lit": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/lit/-/lit-2.3.1.tgz",
-      "integrity": "sha512-TejktDR4mqG3qB32Y8Lm5Lye3c8SUehqz7qRsxe1PqGYL6me2Ef+jeQAEqh20BnnGncv4Yxy2njEIT0kzK1WCw==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/lit/-/lit-2.6.1.tgz",
+      "integrity": "sha512-DT87LD64f8acR7uVp7kZfhLRrHkfC/N4BVzAtnw9Yg8087mbBJ//qedwdwX0kzDbxgPccWRW6mFwGbRQIxy0pw==",
       "requires": {
-        "@lit/reactive-element": "^1.4.0",
+        "@lit/reactive-element": "^1.6.0",
         "lit-element": "^3.2.0",
-        "lit-html": "^2.3.0"
+        "lit-html": "^2.6.0"
       }
     },
     "lit-element": {
@@ -11338,9 +11560,9 @@
       }
     },
     "lit-html": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.3.1.tgz",
-      "integrity": "sha512-FyKH6LTW6aBdkfNhNSHyZTnLgJSTe5hMk7HFtc/+DcN1w74C215q8B+Cfxc2OuIEpBNcEKxgF64qL8as30FDHA==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz",
+      "integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==",
       "requires": {
         "@types/trusted-types": "^2.0.2"
       }
@@ -11463,6 +11685,12 @@
         "brace-expansion": "^1.1.7"
       }
     },
+    "minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "dev": true
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -12286,6 +12514,12 @@
       "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
       "dev": true
     },
+    "typescript": {
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+      "dev": true
+    },
     "universalify": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
diff --git a/package.json b/package.json
index eb78dbb..3583b67 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
   ],
   "devDependencies": {
     "@babel/plugin-transform-modules-commonjs": "^7.20.11",
+    "@lit/localize-tools": "^0.6.7",
     "copy-webpack-plugin": "^9.0.1",
     "css-loader": "^6.2.0",
     "eslint": "^8.30.0",
@@ -44,6 +45,7 @@
   },
   "private": true,
   "dependencies": {
+    "@lit/localize": "^0.11.4",
     "@material/mwc-circular-progress": "^0.27.0",
     "@material/mwc-dialog": "^0.27.0",
     "@material/tooltip": "^12.0.0",
diff --git a/src/common/litI18nUtils.js b/src/common/litI18nUtils.js
new file mode 100644
index 0000000..1f95baa
--- /dev/null
+++ b/src/common/litI18nUtils.js
@@ -0,0 +1,43 @@
+import {configureLocalization, updateWhenLocaleChanges} from '@lit/localize';
+import {LitElement} from 'lit';
+
+import MWI18nClient from '../common/mainWorldI18n/Client.js';
+import {allLocales, sourceLocale, targetLocales} from '../lit-locales/generated/locales.js';
+
+export class I18nLitElement extends LitElement {
+  #MWI18nClient;
+
+  constructor() {
+    super();
+    updateWhenLocaleChanges(this);
+    this.#MWI18nClient = new MWI18nClient();
+    this.#setUpLitL10n();
+  }
+
+  #setUpLitL10n() {
+    let pLocale;
+    if (chrome.i18n) {
+      pLocale = Promise.resolve(chrome.i18n.getUILanguage());
+    } else {
+      pLocale = this.#MWI18nClient.getUILanguage();
+    }
+    pLocale.then(browserLocale => {
+      let locale = browserLocale.substr(0, 2).toLowerCase();
+      if (locale == 'pt') locale = 'pt_BR';
+      const sanitizedLocale = allLocales.includes(locale) ? locale : 'en';
+      setLocale(sanitizedLocale);
+    });
+  }
+}
+
+export const {getLocale, setLocale} = configureLocalization({
+  sourceLocale,
+  targetLocales,
+  loadLocale: locale => {
+    if (!allLocales.includes(locale)) locale = 'en';
+    return import(
+        /* webpackMode: "eager" */
+        /* webpackExclude: /locales\.json$/ */
+        `../lit-locales/generated/${locale}.js`);
+  },
+});
diff --git a/src/contentScripts/communityConsole/flattenThreads/components/ReplyButton.js b/src/contentScripts/communityConsole/flattenThreads/components/ReplyButton.js
index a5bf48d..5dc7d59 100644
--- a/src/contentScripts/communityConsole/flattenThreads/components/ReplyButton.js
+++ b/src/contentScripts/communityConsole/flattenThreads/components/ReplyButton.js
@@ -1,12 +1,14 @@
 import '@material/web/button/outlined-button.js';
 
-import {css, html, LitElement} from 'lit';
+import {msg} from '@lit/localize';
+import {css, html} from 'lit';
 import {waitFor} from 'poll-until-promise';
 
+import {I18nLitElement} from '../../../../common/litI18nUtils.js';
 import {SHARED_MD3_STYLES} from '../../../../common/styles/md3.js';
 import {getExtraInfoNodes} from '../flattenThreads.js';
 
-export default class TwptFlattenThreadReplyButton extends LitElement {
+export default class TwptFlattenThreadReplyButton extends I18nLitElement {
   static properties = {
     extraInfo: {type: Object},
   };
@@ -29,7 +31,9 @@
   render() {
     return html`
       <md-outlined-button
-          label="Reply"
+          label="${msg('Reply', {
+            desc: 'Button which is used to open the reply box.',
+          })}"
           @click=${this.openReplyEditor}>
       </md-outlined-button>
     `;
diff --git a/src/contentScripts/communityConsole/flattenThreads/components/index.js b/src/contentScripts/communityConsole/flattenThreads/components/index.js
index bf532fb..39e8310 100644
--- a/src/contentScripts/communityConsole/flattenThreads/components/index.js
+++ b/src/contentScripts/communityConsole/flattenThreads/components/index.js
@@ -5,14 +5,16 @@
 // Other components imported so they are also injected:
 import './ReplyButton.js';
 
+import {msg} from '@lit/localize';
 import * as DOMPurify from 'dompurify';
-import {css, html, LitElement} from 'lit';
+import {css, html} from 'lit';
 import {classMap} from 'lit/directives/class-map.js';
 import {unsafeHTML} from 'lit/directives/unsafe-html.js';
 
+import {I18nLitElement} from '../../../../common/litI18nUtils.js';
 import {SHARED_MD3_STYLES} from '../../../../common/styles/md3.js';
 
-export default class TwptFlattenThreadQuote extends LitElement {
+export default class TwptFlattenThreadQuote extends I18nLitElement {
   static properties = {
     prevMessage: {type: Object},
     _expanded: {type: Boolean},
@@ -113,6 +115,12 @@
       'quote-container': true,
       'quote-container--expanded': this._expanded,
     });
+    const lessMsg = msg('Less', {
+      desc: 'Button to collapse the quote message (used in the flatten threads feature).',
+    });
+    const moreMsg = msg('More', {
+      desc: 'Button to expand the quote message (used in the flatten threads feature).',
+    });
     return html`
       <div class=${containerClasses}>
         <div class="payload-container">
@@ -126,7 +134,7 @@
         <div class="buttons-row">
           <md-tonal-button
               icon="${this._expanded ? 'expand_less' : 'expand_more'}"
-              label="${this._expanded ? 'Less' : 'More'}"
+              label="${this._expanded ? lessMsg : moreMsg}"
               @click=${this.toggleExpanded}>
           </md-tonal-button>
         </div>
diff --git a/src/lit-locales/generated/.gitignore b/src/lit-locales/generated/.gitignore
new file mode 100644
index 0000000..afe8be7
--- /dev/null
+++ b/src/lit-locales/generated/.gitignore
@@ -0,0 +1,2 @@
+*.js
+*.ts
diff --git a/src/lit-locales/generated/README b/src/lit-locales/generated/README
new file mode 100644
index 0000000..39b1d0d
--- /dev/null
+++ b/src/lit-locales/generated/README
@@ -0,0 +1,5 @@
+This folder contains modules autogenerated by `make lit_localize_build`, ran by
+webpack when serving/building the extension.
+
+Please, do not add any file to this folder other than this document and the
+.gitignore file.
diff --git a/src/lit-locales/source/ar.xlf b/src/lit-locales/source/ar.xlf
new file mode 100644
index 0000000..a029342
--- /dev/null
+++ b/src/lit-locales/source/ar.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="ar" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/ca.xlf b/src/lit-locales/source/ca.xlf
new file mode 100644
index 0000000..bac628b
--- /dev/null
+++ b/src/lit-locales/source/ca.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="ca" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/de.xlf b/src/lit-locales/source/de.xlf
new file mode 100644
index 0000000..fc2ac15
--- /dev/null
+++ b/src/lit-locales/source/de.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="de" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/es.xlf b/src/lit-locales/source/es.xlf
new file mode 100644
index 0000000..feb09aa
--- /dev/null
+++ b/src/lit-locales/source/es.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="es" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/fr.xlf b/src/lit-locales/source/fr.xlf
new file mode 100644
index 0000000..4bcddaf
--- /dev/null
+++ b/src/lit-locales/source/fr.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/id.xlf b/src/lit-locales/source/id.xlf
new file mode 100644
index 0000000..d305689
--- /dev/null
+++ b/src/lit-locales/source/id.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="id" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/it.xlf b/src/lit-locales/source/it.xlf
new file mode 100644
index 0000000..ba1eb1a
--- /dev/null
+++ b/src/lit-locales/source/it.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="it" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/ja.xlf b/src/lit-locales/source/ja.xlf
new file mode 100644
index 0000000..1e8d38e
--- /dev/null
+++ b/src/lit-locales/source/ja.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="ja" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/ko.xlf b/src/lit-locales/source/ko.xlf
new file mode 100644
index 0000000..6a3d938
--- /dev/null
+++ b/src/lit-locales/source/ko.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="ko" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/pl.xlf b/src/lit-locales/source/pl.xlf
new file mode 100644
index 0000000..8d1b568
--- /dev/null
+++ b/src/lit-locales/source/pl.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="pl" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/pt_BR.xlf b/src/lit-locales/source/pt_BR.xlf
new file mode 100644
index 0000000..685d940
--- /dev/null
+++ b/src/lit-locales/source/pt_BR.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="pt_BR" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/ru.xlf b/src/lit-locales/source/ru.xlf
new file mode 100644
index 0000000..7eaa9fc
--- /dev/null
+++ b/src/lit-locales/source/ru.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="ru" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/th.xlf b/src/lit-locales/source/th.xlf
new file mode 100644
index 0000000..b13edb4
--- /dev/null
+++ b/src/lit-locales/source/th.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="th" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/tr.xlf b/src/lit-locales/source/tr.xlf
new file mode 100644
index 0000000..c6468f2
--- /dev/null
+++ b/src/lit-locales/source/tr.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="tr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/src/lit-locales/source/vi.xlf b/src/lit-locales/source/vi.xlf
new file mode 100644
index 0000000..674c7dc
--- /dev/null
+++ b/src/lit-locales/source/vi.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+<file target-language="vi" source-language="en" original="lit-localize-inputs" datatype="plaintext">
+<body>
+<trans-unit id="s0b7ae9543c001867">
+  <source>Reply</source>
+  <note from="lit-localize">Button which is used to open the reply box.</note>
+</trans-unit>
+<trans-unit id="sa5ef80b4bb9b39f8">
+  <source>Less</source>
+  <note from="lit-localize">Button to collapse the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+<trans-unit id="s37a9e8aec5713460">
+  <source>More</source>
+  <note from="lit-localize">Button to expand the quote message (used in the flatten threads feature).</note>
+</trans-unit>
+</body>
+</file>
+</xliff>
diff --git a/webpack.config.js b/webpack.config.js
index c515434..033685f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -93,6 +93,10 @@
     },
     plugins: [
       new WebpackShellPluginNext({
+        onBuildStart: {
+          scripts: ['make lit_localize_build'],
+          blocking: true,
+        },
         onBuildEnd: {
           scripts:
               ['genmanifest -template templates/manifest.gjson -dest ' +
@@ -165,7 +169,8 @@
         new TerserPlugin({
           terserOptions: {
             format: {
-              ascii_only: true, // Due to https://iavm.xyz/b/twpowertools/145#c1
+              ascii_only:
+                  true,  // Due to https://iavm.xyz/b/twpowertools/145#c1
             },
           },
         }),