diff --git a/package-lock.json b/package-lock.json
index 5c23454..b02ec1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2697,87 +2697,91 @@
 				}
 			}
 		},
+		"@jest/types": {
+			"version": "24.8.0",
+			"resolved": "https://registry.npmjs.org/@jest/types/-/types-24.8.0.tgz",
+			"integrity": "sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "^2.0.0",
+				"@types/istanbul-reports": "^1.1.1",
+				"@types/yargs": "^12.0.9"
+			}
+		},
+		"@lingui/babel-plugin-extract-messages": {
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-2.8.3.tgz",
+			"integrity": "sha512-fvGMioLnUsgYzk3afpsYxv8Y8mYHZcYbN8MtEJQFgddO8vlYhZgAi3reWCHUzv4fWw2uGFyv36q6iC0SN9ywwQ==",
+			"dev": true,
+			"requires": {
+				"@lingui/conf": "2.8.3",
+				"babel-generator": "^6.26.1"
+			}
+		},
+		"@lingui/babel-plugin-transform-js": {
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-transform-js/-/babel-plugin-transform-js-2.8.3.tgz",
+			"integrity": "sha512-oztOViWNGak8MbUJECg6IIvMrsCjXkEqETihYwHiN3SebtVYMjvYk50ChXmWdCr4z/b9sysj2fmuaCH37m5mrg==",
+			"dev": true
+		},
 		"@lingui/babel-plugin-transform-react": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-transform-react/-/babel-plugin-transform-react-2.7.0.tgz",
-			"integrity": "sha512-wRGoI7ne0ogqEGQiI2DJx0IXrWnh2x9/XPPFDO+9+Zx+EUZ/PXNzMdnv0ZNeWHQw59ye1dh1/R1wJXDGzvzxpA==",
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-transform-react/-/babel-plugin-transform-react-2.8.3.tgz",
+			"integrity": "sha512-kozAtkaCEcCSFbiuZJzJd2febZTPaokUBuwPPKfehGp8v8MNPJK4kGarBNuKE8YOhkT6EpniZWk6Gk4HzjvfnA==",
 			"dev": true
 		},
 		"@lingui/cli": {
-			"version": "2.7.4",
-			"resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-2.7.4.tgz",
-			"integrity": "sha512-Px/b3N8ryNdpnPj2pduX+pj91I7Zm3dFKj8dXRbgFmVjXcf3od0hK8yoPj9nBuuTa9VBB4wbZwBJSwuqYuHfgg==",
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-2.8.3.tgz",
+			"integrity": "sha512-0QrTIjoRwjt0DdOg+ZQy8B7QA0E+3r710GsJtOayTVAgCZA/xfTrUInjwsTB6afnHBEbA3jx/4FV9URwuy6Kbw==",
 			"dev": true,
 			"requires": {
-				"@lingui/babel-plugin-extract-messages": "2.7.4",
-				"@lingui/babel-plugin-transform-js": "2.7.4",
-				"@lingui/babel-plugin-transform-react": "2.7.4",
-				"@lingui/conf": "2.7.4",
+				"@lingui/babel-plugin-extract-messages": "2.8.3",
+				"@lingui/babel-plugin-transform-js": "2.8.3",
+				"@lingui/babel-plugin-transform-react": "2.8.3",
+				"@lingui/conf": "2.8.3",
 				"babel-generator": "^6.26.1",
 				"babel-plugin-syntax-jsx": "^6.18.0",
 				"babel-runtime": "^6.26.0",
 				"babel-types": "^6.26.0",
 				"babylon": "^6.18.0",
-				"bcp-47": "^1.0.4",
+				"bcp-47": "^1.0.5",
 				"chalk": "^2.3.0",
 				"cli-table": "^0.3.1",
-				"commander": "^2.17.1",
+				"commander": "^2.20.0",
 				"date-fns": "^1.29.0",
 				"fuzzaldrin": "^2.1.0",
-				"glob": "^7.1.2",
-				"inquirer": "^6.2.0",
+				"glob": "^7.1.4",
+				"inquirer": "^6.3.1",
 				"make-plural": "^4.1.1",
 				"messageformat-parser": "^2.0.0",
 				"mkdirp": "^0.5.1",
 				"opencollective": "^1.0.3",
-				"ora": "^3.0.0",
+				"ora": "^3.4.0",
 				"pofile": "^1.0.11",
 				"pseudolocale": "^1.1.0",
-				"ramda": "^0.25.0",
+				"ramda": "^0.26.1",
 				"typescript": "^2.9.2"
 			},
 			"dependencies": {
-				"@lingui/babel-plugin-extract-messages": {
-					"version": "2.7.4",
-					"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-2.7.4.tgz",
-					"integrity": "sha512-/0XNXLg3gKLvmvaQ9+A2lxuRtG6g1zhp3KGMdC+cwUU4fX5Sfim3x3vRxlkMk69j/GkKC5OlKKTPZlI05NsReg==",
-					"dev": true,
-					"requires": {
-						"@lingui/conf": "2.7.4",
-						"babel-generator": "^6.26.1"
-					}
-				},
-				"@lingui/babel-plugin-transform-js": {
-					"version": "2.7.4",
-					"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-transform-js/-/babel-plugin-transform-js-2.7.4.tgz",
-					"integrity": "sha512-jqs1AR3507e1vqaVQB0bG15p5VaujlD48Vm7/ElL3ieFvx/gyvZp5b1wv/A8kpVuPcEhFm7oWJzeUfkh1mdOTg==",
+				"ansi-regex": {
+					"version": "4.1.0",
+					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+					"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
 					"dev": true
 				},
-				"@lingui/babel-plugin-transform-react": {
-					"version": "2.7.4",
-					"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-transform-react/-/babel-plugin-transform-react-2.7.4.tgz",
-					"integrity": "sha512-U4ocmtqOIjqDQX9tYrOLDNR7Tp8EmDPoBUtXyXfAPb4ukA3CePphuz89N8lDZVsTUQwBDNDynP/3qiLr1pW4QQ==",
-					"dev": true
-				},
-				"@lingui/conf": {
-					"version": "2.7.4",
-					"resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-2.7.4.tgz",
-					"integrity": "sha512-v/tr1aLYrUozu09yHBzRHBB2gPYD8Vwth51RuTOyzsthQVAtfKY7VV7m2wB0JQFMD9gGbPE5a+roqH6RkB7qUw==",
-					"dev": true,
-					"requires": {
-						"chalk": "^2.3.0",
-						"cosmiconfig": "^5.0.6",
-						"jest-regex-util": "^23.3.0",
-						"jest-validate": "^23.5.0",
-						"pkg-conf": "^2.1.0"
-					}
-				},
 				"chardet": {
 					"version": "0.7.0",
 					"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
 					"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
 					"dev": true
 				},
+				"commander": {
+					"version": "2.20.0",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+					"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+					"dev": true
+				},
 				"external-editor": {
 					"version": "3.1.0",
 					"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -2789,10 +2793,24 @@
 						"tmp": "^0.0.33"
 					}
 				},
+				"glob": {
+					"version": "7.1.4",
+					"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+					"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+					"dev": true,
+					"requires": {
+						"fs.realpath": "^1.0.0",
+						"inflight": "^1.0.4",
+						"inherits": "2",
+						"minimatch": "^3.0.4",
+						"once": "^1.3.0",
+						"path-is-absolute": "^1.0.0"
+					}
+				},
 				"inquirer": {
-					"version": "6.2.2",
-					"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz",
-					"integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==",
+					"version": "6.5.0",
+					"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz",
+					"integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==",
 					"dev": true,
 					"requires": {
 						"ansi-escapes": "^3.2.0",
@@ -2801,120 +2819,13 @@
 						"cli-width": "^2.0.0",
 						"external-editor": "^3.0.3",
 						"figures": "^2.0.0",
-						"lodash": "^4.17.11",
+						"lodash": "^4.17.12",
 						"mute-stream": "0.0.7",
 						"run-async": "^2.2.0",
 						"rxjs": "^6.4.0",
 						"string-width": "^2.1.0",
-						"strip-ansi": "^5.0.0",
+						"strip-ansi": "^5.1.0",
 						"through": "^2.3.6"
-					},
-					"dependencies": {
-						"ansi-escapes": {
-							"version": "3.2.0",
-							"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
-							"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
-							"dev": true
-						},
-						"cli-cursor": {
-							"version": "2.1.0",
-							"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-							"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-							"dev": true,
-							"requires": {
-								"restore-cursor": "^2.0.0"
-							}
-						},
-						"cli-width": {
-							"version": "2.2.0",
-							"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
-							"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
-							"dev": true
-						},
-						"figures": {
-							"version": "2.0.0",
-							"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
-							"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
-							"dev": true,
-							"requires": {
-								"escape-string-regexp": "^1.0.5"
-							}
-						},
-						"mute-stream": {
-							"version": "0.0.7",
-							"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
-							"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
-							"dev": true
-						},
-						"run-async": {
-							"version": "2.3.0",
-							"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
-							"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
-							"dev": true,
-							"requires": {
-								"is-promise": "^2.1.0"
-							}
-						},
-						"rxjs": {
-							"version": "6.4.0",
-							"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
-							"integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
-							"dev": true,
-							"requires": {
-								"tslib": "^1.9.0"
-							}
-						},
-						"string-width": {
-							"version": "2.1.1",
-							"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-							"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-							"dev": true,
-							"requires": {
-								"is-fullwidth-code-point": "^2.0.0",
-								"strip-ansi": "^4.0.0"
-							},
-							"dependencies": {
-								"strip-ansi": {
-									"version": "4.0.0",
-									"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-									"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-									"dev": true,
-									"requires": {
-										"ansi-regex": "^3.0.0"
-									}
-								}
-							}
-						},
-						"through": {
-							"version": "2.3.8",
-							"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-							"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
-							"dev": true
-						}
-					}
-				},
-				"jest-get-type": {
-					"version": "22.4.3",
-					"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz",
-					"integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==",
-					"dev": true
-				},
-				"jest-regex-util": {
-					"version": "23.3.0",
-					"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz",
-					"integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=",
-					"dev": true
-				},
-				"jest-validate": {
-					"version": "23.6.0",
-					"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz",
-					"integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==",
-					"dev": true,
-					"requires": {
-						"chalk": "^2.0.1",
-						"jest-get-type": "^22.1.0",
-						"leven": "^2.1.0",
-						"pretty-format": "^23.6.0"
 					}
 				},
 				"lodash": {
@@ -2923,55 +2834,11 @@
 					"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
 					"dev": true
 				},
-				"ora": {
-					"version": "3.1.0",
-					"resolved": "https://registry.npmjs.org/ora/-/ora-3.1.0.tgz",
-					"integrity": "sha512-vRBPaNCclUi8pUxRF/G8+5qEQkc6EgzKK1G2ZNJUIGu088Un5qIxFXeDgymvPRM9nmrcUOGzQgS1Vmtz+NtlMw==",
-					"dev": true,
-					"requires": {
-						"chalk": "^2.4.2",
-						"cli-cursor": "^2.1.0",
-						"cli-spinners": "^1.3.1",
-						"log-symbols": "^2.2.0",
-						"strip-ansi": "^5.0.0",
-						"wcwidth": "^1.0.1"
-					},
-					"dependencies": {
-						"cli-spinners": {
-							"version": "1.3.1",
-							"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
-							"integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==",
-							"dev": true
-						},
-						"log-symbols": {
-							"version": "2.2.0",
-							"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-							"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
-							"dev": true,
-							"requires": {
-								"chalk": "^2.0.1"
-							}
-						},
-						"wcwidth": {
-							"version": "1.0.1",
-							"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
-							"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
-							"dev": true,
-							"requires": {
-								"defaults": "^1.0.3"
-							}
-						}
-					}
-				},
-				"pretty-format": {
-					"version": "23.6.0",
-					"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
-					"integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==",
-					"dev": true,
-					"requires": {
-						"ansi-regex": "^3.0.0",
-						"ansi-styles": "^3.2.0"
-					}
+				"ramda": {
+					"version": "0.26.1",
+					"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz",
+					"integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==",
+					"dev": true
 				},
 				"strip-ansi": {
 					"version": "5.2.0",
@@ -2980,23 +2847,6 @@
 					"dev": true,
 					"requires": {
 						"ansi-regex": "^4.1.0"
-					},
-					"dependencies": {
-						"ansi-regex": {
-							"version": "4.1.0",
-							"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-							"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-							"dev": true
-						}
-					}
-				},
-				"tmp": {
-					"version": "0.0.33",
-					"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-					"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-					"dev": true,
-					"requires": {
-						"os-tmpdir": "~1.0.2"
 					}
 				},
 				"typescript": {
@@ -3007,10 +2857,97 @@
 				}
 			}
 		},
+		"@lingui/conf": {
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-2.8.3.tgz",
+			"integrity": "sha512-XGrInpIZ59xrjNefEeRXbFbwcdkfiqMrx0wa3wS6ZD8cTEW+YuKCBeDGo9/Fv/crhZ4GbmqcYyNFyikGaB+ZyQ==",
+			"dev": true,
+			"requires": {
+				"chalk": "^2.3.0",
+				"cosmiconfig": "^5.2.1",
+				"jest-regex-util": "^24.3.0",
+				"jest-validate": "^24.8.0",
+				"pkg-conf": "^3.1.0"
+			},
+			"dependencies": {
+				"ansi-regex": {
+					"version": "4.1.0",
+					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+					"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+					"dev": true
+				},
+				"camelcase": {
+					"version": "5.3.1",
+					"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+					"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+					"dev": true
+				},
+				"cosmiconfig": {
+					"version": "5.2.1",
+					"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+					"integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+					"dev": true,
+					"requires": {
+						"import-fresh": "^2.0.0",
+						"is-directory": "^0.3.1",
+						"js-yaml": "^3.13.1",
+						"parse-json": "^4.0.0"
+					}
+				},
+				"jest-get-type": {
+					"version": "24.8.0",
+					"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.8.0.tgz",
+					"integrity": "sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==",
+					"dev": true
+				},
+				"jest-regex-util": {
+					"version": "24.3.0",
+					"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz",
+					"integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==",
+					"dev": true
+				},
+				"jest-validate": {
+					"version": "24.8.0",
+					"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.8.0.tgz",
+					"integrity": "sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==",
+					"dev": true,
+					"requires": {
+						"@jest/types": "^24.8.0",
+						"camelcase": "^5.0.0",
+						"chalk": "^2.0.1",
+						"jest-get-type": "^24.8.0",
+						"leven": "^2.1.0",
+						"pretty-format": "^24.8.0"
+					}
+				},
+				"js-yaml": {
+					"version": "3.13.1",
+					"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+					"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+					"dev": true,
+					"requires": {
+						"argparse": "^1.0.7",
+						"esprima": "^4.0.0"
+					}
+				},
+				"pretty-format": {
+					"version": "24.8.0",
+					"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.8.0.tgz",
+					"integrity": "sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==",
+					"dev": true,
+					"requires": {
+						"@jest/types": "^24.8.0",
+						"ansi-regex": "^4.0.0",
+						"ansi-styles": "^3.2.0",
+						"react-is": "^16.8.4"
+					}
+				}
+			}
+		},
 		"@lingui/core": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/@lingui/core/-/core-2.7.0.tgz",
-			"integrity": "sha512-002qfPkrwW1d0Br44aR287OTFh+s035f3n42rZOrnNRgTu17l2qblEJX0dj0+OJRXy56sgqkKFDObvjvkTrAjQ==",
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/core/-/core-2.8.3.tgz",
+			"integrity": "sha512-Y2Oh0IW7UKki3MADnMZkHN4+jl8ogR82uq8j4HVS1bixI+fwnZgR+A0D+0S6BuLh0quXRqOCfHIJxUA7dph9xw==",
 			"requires": {
 				"babel-runtime": "^6.26.0",
 				"make-plural": "^4.1.1",
@@ -3018,25 +2955,24 @@
 			}
 		},
 		"@lingui/macro": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-2.7.0.tgz",
-			"integrity": "sha512-RFne6j7OUDh4qy2LKprgL7Si75uoYFGhIxFDiAoEQXYCDtNgDozU9oXuOiRECinH3/rt34leaJh3nAGSvcrHVw==",
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-2.8.3.tgz",
+			"integrity": "sha512-gs3GO+Lwf7r8dO0XwDX9vFuh+7x4/cUz+iaMb5aBYgVsgWc9UU0RAn27ll4kORcvVzY/rVHEPGSoDUJlPIbwlw==",
 			"dev": true,
 			"requires": {
-				"@lingui/babel-plugin-transform-react": "2.7.0",
-				"babel-plugin-macros": "^2.2.0"
+				"@lingui/babel-plugin-transform-react": "2.8.3"
 			}
 		},
 		"@lingui/react": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/@lingui/react/-/react-2.7.0.tgz",
-			"integrity": "sha512-3/P+KNbOK38fOveY7jYlALzngUl6Eq5jwnqOZVYUwaSs+qKKKcWGewyfxBxw/blkaw5ukW7tdZF/cqOitMEFbw==",
+			"version": "2.8.3",
+			"resolved": "https://registry.npmjs.org/@lingui/react/-/react-2.8.3.tgz",
+			"integrity": "sha512-sW8Tm+LQKIYKy6IjdDg5/h7uxL2WGUVbp+FmigB63MmUR/i40gPG2IKRIg0ubcL9Hu9hZpqkSxT0aKigFBrsnQ==",
 			"requires": {
-				"@lingui/core": "2.7.0",
+				"@lingui/core": "2.8.3",
 				"babel-runtime": "^6.26.0",
 				"hash-sum": "^1.0.2",
-				"hoist-non-react-statics": "3.0.1",
-				"prop-types": "^15.6.2"
+				"hoist-non-react-statics": "3.3.0",
+				"prop-types": "^15.7.2"
 			}
 		},
 		"@mrmlnc/readdir-enhanced": {
@@ -3120,6 +3056,31 @@
 				"@types/node": "*"
 			}
 		},
+		"@types/istanbul-lib-coverage": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
+			"integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==",
+			"dev": true
+		},
+		"@types/istanbul-lib-report": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz",
+			"integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "*"
+			}
+		},
+		"@types/istanbul-reports": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz",
+			"integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==",
+			"dev": true,
+			"requires": {
+				"@types/istanbul-lib-coverage": "*",
+				"@types/istanbul-lib-report": "*"
+			}
+		},
 		"@types/minimatch": {
 			"version": "3.0.3",
 			"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -3138,6 +3099,12 @@
 			"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
 			"dev": true
 		},
+		"@types/yargs": {
+			"version": "12.0.12",
+			"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz",
+			"integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==",
+			"dev": true
+		},
 		"@webassemblyjs/ast": {
 			"version": "1.8.5",
 			"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@@ -3348,6 +3315,7 @@
 			"version": "1.3.5",
 			"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
 			"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+			"dev": true,
 			"requires": {
 				"mime-types": "~2.1.18",
 				"negotiator": "0.6.1"
@@ -3456,7 +3424,8 @@
 		"ansi-colors": {
 			"version": "2.0.5",
 			"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz",
-			"integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw=="
+			"integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==",
+			"dev": true
 		},
 		"ansi-cyan": {
 			"version": "0.1.1",
@@ -3468,15 +3437,16 @@
 			}
 		},
 		"ansi-escapes": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
-			"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+			"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
 			"dev": true
 		},
 		"ansi-gray": {
 			"version": "0.1.1",
 			"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
 			"integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
+			"dev": true,
 			"requires": {
 				"ansi-wrap": "0.1.0"
 			}
@@ -3514,7 +3484,8 @@
 		"ansi-wrap": {
 			"version": "0.1.0",
 			"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
-			"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768="
+			"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
+			"dev": true
 		},
 		"any-observable": {
 			"version": "0.3.0",
@@ -4744,13 +4715,38 @@
 			"dev": true
 		},
 		"babel-plugin-macros": {
-			"version": "2.5.0",
-			"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.5.0.tgz",
-			"integrity": "sha512-BWw0lD0kVZAXRD3Od1kMrdmfudqzDzYv2qrN3l2ISR1HVp1EgLKfbOrYV9xmY5k3qx3RIu5uPAUZZZHpo0o5Iw==",
+			"version": "2.6.1",
+			"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz",
+			"integrity": "sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ==",
 			"dev": true,
 			"requires": {
-				"cosmiconfig": "^5.0.5",
-				"resolve": "^1.8.1"
+				"@babel/runtime": "^7.4.2",
+				"cosmiconfig": "^5.2.0",
+				"resolve": "^1.10.0"
+			},
+			"dependencies": {
+				"cosmiconfig": {
+					"version": "5.2.1",
+					"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+					"integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+					"dev": true,
+					"requires": {
+						"import-fresh": "^2.0.0",
+						"is-directory": "^0.3.1",
+						"js-yaml": "^3.13.1",
+						"parse-json": "^4.0.0"
+					}
+				},
+				"js-yaml": {
+					"version": "3.13.1",
+					"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+					"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+					"dev": true,
+					"requires": {
+						"argparse": "^1.0.7",
+						"esprima": "^4.0.0"
+					}
+				}
 			}
 		},
 		"babel-plugin-minify-builtins": {
@@ -5140,12 +5136,13 @@
 		"batch": {
 			"version": "0.6.1",
 			"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-			"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
+			"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+			"dev": true
 		},
 		"bcp-47": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-1.0.4.tgz",
-			"integrity": "sha512-KquGHKBVXDBnOOntjqkqINNyNX0eKhDXYbK+83pDJXWO7lV6D7Ey1IQNIDbVQOHxNv6rdynnfS/RfPLVz5X0WA==",
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-1.0.5.tgz",
+			"integrity": "sha512-BiuU8i9Rp2ssV8Tsh/h/+Dkdh2M38gKxP90p1VXf079YHqg4Iye58W+CO2OUy36yXbUVC747rypATdRsCtKneA==",
 			"dev": true,
 			"requires": {
 				"is-alphabetical": "^1.0.0",
@@ -5232,6 +5229,7 @@
 			"version": "5.1.0",
 			"resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz",
 			"integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=",
+			"dev": true,
 			"requires": {
 				"continuable-cache": "^0.3.1",
 				"error": "^7.0.0",
@@ -5242,12 +5240,14 @@
 				"bytes": {
 					"version": "1.0.0",
 					"resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz",
-					"integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g="
+					"integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=",
+					"dev": true
 				},
 				"raw-body": {
 					"version": "1.1.7",
 					"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz",
 					"integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=",
+					"dev": true,
 					"requires": {
 						"bytes": "1",
 						"string_decoder": "0.10"
@@ -6552,7 +6552,8 @@
 		"color-support": {
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
-			"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
+			"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+			"dev": true
 		},
 		"colors": {
 			"version": "1.0.3",
@@ -6760,6 +6761,7 @@
 			"version": "3.6.6",
 			"resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
 			"integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
+			"dev": true,
 			"requires": {
 				"debug": "2.6.9",
 				"finalhandler": "1.1.0",
@@ -6776,7 +6778,8 @@
 		"connect-livereload": {
 			"version": "0.6.1",
 			"resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz",
-			"integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g=="
+			"integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==",
+			"dev": true
 		},
 		"console-browserify": {
 			"version": "1.1.0",
@@ -6841,7 +6844,8 @@
 		"continuable-cache": {
 			"version": "0.3.1",
 			"resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz",
-			"integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8="
+			"integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=",
+			"dev": true
 		},
 		"convert-source-map": {
 			"version": "1.6.0",
@@ -7600,6 +7604,7 @@
 			"version": "2.6.9",
 			"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 			"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+			"dev": true,
 			"requires": {
 				"ms": "2.0.0"
 			}
@@ -7869,7 +7874,8 @@
 		"depd": {
 			"version": "1.1.2",
 			"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-			"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+			"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+			"dev": true
 		},
 		"dependency-tree": {
 			"version": "6.5.0",
@@ -7919,7 +7925,8 @@
 		"destroy": {
 			"version": "1.0.4",
 			"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-			"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+			"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+			"dev": true
 		},
 		"detect-file": {
 			"version": "1.0.0",
@@ -8398,7 +8405,8 @@
 		"ee-first": {
 			"version": "1.1.1",
 			"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-			"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+			"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+			"dev": true
 		},
 		"ejs": {
 			"version": "2.6.1",
@@ -8505,7 +8513,8 @@
 		"encodeurl": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-			"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+			"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+			"dev": true
 		},
 		"encoding": {
 			"version": "0.1.12",
@@ -8644,6 +8653,7 @@
 			"version": "7.0.2",
 			"resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz",
 			"integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=",
+			"dev": true,
 			"requires": {
 				"string-template": "~0.2.1",
 				"xtend": "~4.0.0"
@@ -8698,7 +8708,8 @@
 		"escape-html": {
 			"version": "1.0.3",
 			"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-			"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+			"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+			"dev": true
 		},
 		"escape-string-regexp": {
 			"version": "1.0.5",
@@ -9076,7 +9087,8 @@
 		"etag": {
 			"version": "1.8.1",
 			"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-			"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+			"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+			"dev": true
 		},
 		"event-stream": {
 			"version": "4.0.1",
@@ -9605,6 +9617,7 @@
 			"version": "1.3.3",
 			"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
 			"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
+			"dev": true,
 			"requires": {
 				"ansi-gray": "^0.1.1",
 				"color-support": "^1.1.3",
@@ -9693,6 +9706,7 @@
 			"version": "0.10.0",
 			"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
 			"integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+			"dev": true,
 			"requires": {
 				"websocket-driver": ">=0.5.1"
 			}
@@ -9859,6 +9873,7 @@
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
 			"integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+			"dev": true,
 			"requires": {
 				"debug": "2.6.9",
 				"encodeurl": "~1.0.1",
@@ -9872,7 +9887,8 @@
 				"statuses": {
 					"version": "1.3.1",
 					"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
-					"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+					"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+					"dev": true
 				}
 			}
 		},
@@ -10188,7 +10204,8 @@
 		"fresh": {
 			"version": "0.5.2",
 			"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-			"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+			"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+			"dev": true
 		},
 		"from": {
 			"version": "0.1.7",
@@ -11848,6 +11865,7 @@
 			"version": "5.7.0",
 			"resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz",
 			"integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==",
+			"dev": true,
 			"requires": {
 				"ansi-colors": "^2.0.5",
 				"connect": "^3.6.6",
@@ -12568,11 +12586,11 @@
 			}
 		},
 		"hoist-non-react-statics": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.0.1.tgz",
-			"integrity": "sha512-1kXwPsOi0OGQIZNVMPvgWJ9tSnGMiMfJdihqEzrPEXlHOBh9AAHXX/QYmAJTXztnz/K+PQ8ryCb4eGaN6HlGbQ==",
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
+			"integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
 			"requires": {
-				"react-is": "^16.3.2"
+				"react-is": "^16.7.0"
 			}
 		},
 		"home-or-tmp": {
@@ -12767,6 +12785,7 @@
 			"version": "1.6.3",
 			"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
 			"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+			"dev": true,
 			"requires": {
 				"depd": "~1.1.2",
 				"inherits": "2.0.3",
@@ -14948,7 +14967,8 @@
 		"livereload-js": {
 			"version": "2.4.0",
 			"resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz",
-			"integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw=="
+			"integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==",
+			"dev": true
 		},
 		"load-json-file": {
 			"version": "1.1.0",
@@ -15525,7 +15545,8 @@
 		"map-stream": {
 			"version": "0.0.7",
 			"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
-			"integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg="
+			"integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=",
+			"dev": true
 		},
 		"map-visit": {
 			"version": "1.0.0",
@@ -15817,12 +15838,14 @@
 		"mime-db": {
 			"version": "1.38.0",
 			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
-			"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
+			"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==",
+			"dev": true
 		},
 		"mime-types": {
 			"version": "2.1.22",
 			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
 			"integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+			"dev": true,
 			"requires": {
 				"mime-db": "~1.38.0"
 			}
@@ -16055,7 +16078,8 @@
 		"ms": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+			"dev": true
 		},
 		"multicast-dns": {
 			"version": "6.2.3",
@@ -16168,7 +16192,8 @@
 		"negotiator": {
 			"version": "0.6.1",
 			"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-			"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+			"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+			"dev": true
 		},
 		"neo-async": {
 			"version": "2.6.1",
@@ -16743,6 +16768,7 @@
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
 			"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+			"dev": true,
 			"requires": {
 				"ee-first": "1.1.1"
 			}
@@ -16784,6 +16810,12 @@
 				"opn": "4.0.2"
 			},
 			"dependencies": {
+				"ansi-escapes": {
+					"version": "1.4.0",
+					"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+					"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+					"dev": true
+				},
 				"ansi-styles": {
 					"version": "2.2.1",
 					"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@@ -17231,7 +17263,8 @@
 		"parse-node-version": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
-			"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
+			"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+			"dev": true
 		},
 		"parse-passwd": {
 			"version": "1.0.0",
@@ -17266,7 +17299,8 @@
 		"parseurl": {
 			"version": "1.3.2",
 			"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
-			"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+			"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+			"dev": true
 		},
 		"pascalcase": {
 			"version": "0.1.1",
@@ -17403,31 +17437,81 @@
 			}
 		},
 		"pkg-conf": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
-			"integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=",
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz",
+			"integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==",
 			"dev": true,
 			"requires": {
-				"find-up": "^2.0.0",
-				"load-json-file": "^4.0.0"
+				"find-up": "^3.0.0",
+				"load-json-file": "^5.2.0"
 			},
 			"dependencies": {
-				"load-json-file": {
-					"version": "4.0.0",
-					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
-					"integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+				"find-up": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+					"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
 					"dev": true,
 					"requires": {
-						"graceful-fs": "^4.1.2",
-						"parse-json": "^4.0.0",
-						"pify": "^3.0.0",
-						"strip-bom": "^3.0.0"
+						"locate-path": "^3.0.0"
 					}
 				},
-				"pify": {
+				"load-json-file": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+					"integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+					"dev": true,
+					"requires": {
+						"graceful-fs": "^4.1.15",
+						"parse-json": "^4.0.0",
+						"pify": "^4.0.1",
+						"strip-bom": "^3.0.0",
+						"type-fest": "^0.3.0"
+					}
+				},
+				"locate-path": {
 					"version": "3.0.0",
-					"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-					"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+					"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+					"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+					"dev": true,
+					"requires": {
+						"p-locate": "^3.0.0",
+						"path-exists": "^3.0.0"
+					}
+				},
+				"p-limit": {
+					"version": "2.2.0",
+					"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+					"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+					"dev": true,
+					"requires": {
+						"p-try": "^2.0.0"
+					}
+				},
+				"p-locate": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+					"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+					"dev": true,
+					"requires": {
+						"p-limit": "^2.0.0"
+					}
+				},
+				"p-try": {
+					"version": "2.2.0",
+					"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+					"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+					"dev": true
+				},
+				"path-exists": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+					"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+					"dev": true
+				},
+				"pify": {
+					"version": "4.0.1",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+					"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
 					"dev": true
 				}
 			}
@@ -17569,9 +17653,9 @@
 			"dev": true
 		},
 		"pofile": {
-			"version": "1.0.11",
-			"resolved": "https://registry.npmjs.org/pofile/-/pofile-1.0.11.tgz",
-			"integrity": "sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg==",
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/pofile/-/pofile-1.1.0.tgz",
+			"integrity": "sha512-6XYcNkXWGiJ2CVXogTP7uJ6ZXQCldYLZc16wgRp8tqRaBTTyIfF+TUT3EQJPXTLAT7OTPpTAoaFdoXKfaTRU1w==",
 			"dev": true
 		},
 		"portfinder": {
@@ -19200,7 +19284,8 @@
 		"qs": {
 			"version": "6.5.2",
 			"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-			"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+			"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+			"dev": true
 		},
 		"query-string": {
 			"version": "5.1.1",
@@ -19290,7 +19375,8 @@
 		"range-parser": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-			"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+			"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+			"dev": true
 		},
 		"raw-body": {
 			"version": "2.3.3",
@@ -20147,7 +20233,8 @@
 		"safe-json-parse": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz",
-			"integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c="
+			"integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=",
+			"dev": true
 		},
 		"safe-regex": {
 			"version": "1.1.0",
@@ -20337,6 +20424,7 @@
 			"version": "0.16.2",
 			"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
 			"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+			"dev": true,
 			"requires": {
 				"debug": "2.6.9",
 				"depd": "~1.1.2",
@@ -20356,7 +20444,8 @@
 				"mime": {
 					"version": "1.4.1",
 					"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
-					"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+					"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+					"dev": true
 				}
 			}
 		},
@@ -20381,6 +20470,7 @@
 			"version": "1.9.1",
 			"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
 			"integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+			"dev": true,
 			"requires": {
 				"accepts": "~1.3.4",
 				"batch": "0.6.1",
@@ -20395,6 +20485,7 @@
 			"version": "1.13.2",
 			"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
 			"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+			"dev": true,
 			"requires": {
 				"encodeurl": "~1.0.2",
 				"escape-html": "~1.0.3",
@@ -20457,7 +20548,8 @@
 		"setprototypeof": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-			"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+			"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+			"dev": true
 		},
 		"sha.js": {
 			"version": "2.4.11",
@@ -21274,7 +21366,8 @@
 		"statuses": {
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-			"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+			"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+			"dev": true
 		},
 		"stealthy-require": {
 			"version": "1.1.1",
@@ -21381,7 +21474,8 @@
 		"string-template": {
 			"version": "0.2.1",
 			"resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz",
-			"integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0="
+			"integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=",
+			"dev": true
 		},
 		"string-width": {
 			"version": "2.1.1",
@@ -21407,7 +21501,8 @@
 		"string_decoder": {
 			"version": "0.10.31",
 			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-			"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+			"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+			"dev": true
 		},
 		"stringify-object": {
 			"version": "3.3.0",
@@ -22054,7 +22149,8 @@
 		"time-stamp": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
-			"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM="
+			"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
+			"dev": true
 		},
 		"time-zone": {
 			"version": "1.0.0",
@@ -22087,6 +22183,7 @@
 			"version": "1.1.1",
 			"resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz",
 			"integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==",
+			"dev": true,
 			"requires": {
 				"body": "^5.1.0",
 				"debug": "^3.1.0",
@@ -22100,6 +22197,7 @@
 					"version": "3.2.6",
 					"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
 					"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+					"dev": true,
 					"requires": {
 						"ms": "^2.1.1"
 					}
@@ -22107,10 +22205,20 @@
 				"ms": {
 					"version": "2.1.2",
 					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-					"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+					"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+					"dev": true
 				}
 			}
 		},
+		"tmp": {
+			"version": "0.0.33",
+			"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+			"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+			"dev": true,
+			"requires": {
+				"os-tmpdir": "~1.0.2"
+			}
+		},
 		"tmpl": {
 			"version": "1.0.4",
 			"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -22518,7 +22626,8 @@
 		"unpipe": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-			"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+			"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+			"dev": true
 		},
 		"unquote": {
 			"version": "1.1.1",
@@ -22752,7 +22861,8 @@
 		"utils-merge": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-			"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+			"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+			"dev": true
 		},
 		"uuid": {
 			"version": "3.3.2",
diff --git a/package.json b/package.json
index 88dd9e4..f88788d 100644
--- a/package.json
+++ b/package.json
@@ -36,9 +36,9 @@
 		"@11ty/eleventy": "^0.7.1",
 		"@lingui/cli": "^2.8.3",
 		"@lingui/macro": "^2.8.3",
-		"babel-core": "^6.26.3",
 		"babel-eslint": "^7.2.3",
 		"babel-minify": "^0.2.0",
+		"babel-plugin-macros": "^2.6.1",
 		"eslint": "^4.9.0",
 		"eslint-config-prettier": "^2.3.0",
 		"eslint-config-synacor": "^2.0.2",
@@ -60,17 +60,17 @@
 		"preact-cli": "^3.0.0-rc.3",
 		"preact-render-spy": "^1.2.1",
 		"run-sequence": "^2.2.1",
-		"sw-precache": "^5.2.0"
+		"sw-precache": "^5.2.0",
+		"gulp-connect": "^5.7.0"
 	},
 	"dependencies": {
 		"@emmetio/codemirror-plugin": "^0.5.4",
-		"@lingui/react": "^2.7.4",
+		"@lingui/react": "^2.8.3",
 		"code-blast-codemirror": "chinchang/code-blast-codemirror#web-maker",
 		"codemirror": "^5.37.0",
 		"copy-webpack-plugin": "^4.5.1",
 		"esprima": "^4.0.0",
 		"firebase": "^5.5.8",
-		"gulp-connect": "^5.7.0",
 		"jszip": "^3.1.5",
 		"preact": "^10.0.0-rc.0",
 		"preact-portal": "^1.1.3",
diff --git a/src/components/AddLibrary.jsx b/src/components/AddLibrary.jsx
index 6cc0cea..14284ca 100644
--- a/src/components/AddLibrary.jsx
+++ b/src/components/AddLibrary.jsx
@@ -2,6 +2,8 @@ import { h, Component } from 'preact';
 import { jsLibs, cssLibs } from '../libraryList';
 import { trackEvent } from '../analytics';
 import { LibraryAutoSuggest } from './LibraryAutoSuggest';
+import { Trans, t } from '@lingui/macro';
+import { I18n } from '@lingui/react';
 
 export default class AddLibrary extends Component {
 	constructor(props) {
@@ -58,86 +60,104 @@ export default class AddLibrary extends Component {
 	}
 	render() {
 		return (
-			<div>
-				<h1>Add Library</h1>
+			<I18n>
+				{({ i18n }) => (
+					<div>
+						<h1>
+							<Trans>Add Library</Trans>
+						</h1>
 
-				<div class="flex flex-v-center">
-					<svg style="width: 30px; height: 30px;fill:rgb(255,255,255,0.5)">
-						<use xlinkHref="#search" />
-					</svg>
-					<LibraryAutoSuggest
-						fullWidth
-						onSelect={this.suggestionSelectHandler.bind(this)}
-					>
-						<input
-							type="text"
-							id="externalLibrarySearchInput"
+						<div class="flex flex-v-center">
+							<svg style="width: 30px; height: 30px;fill:rgb(255,255,255,0.5)">
+								<use xlinkHref="#search" />
+							</svg>
+							<LibraryAutoSuggest
+								fullWidth
+								onSelect={this.suggestionSelectHandler.bind(this)}
+							>
+								<input
+									type="text"
+									id="externalLibrarySearchInput"
+									class="full-width"
+									placeholder={i18n._(t`Type here to search libraries`)}
+								/>
+							</LibraryAutoSuggest>
+						</div>
+						<div class="tar opacity--70">
+							<small>
+								<Trans>Powered by cdnjs</Trans>
+							</small>
+						</div>
+						<div style="margin:20px 0;">
+							<Trans>Choose from popular libraries</Trans>:{' '}
+							<select
+								name=""
+								id="js-add-library-select"
+								onChange={this.onSelectChange.bind(this)}
+							>
+								<option value="">-------</option>
+								<optgroup label="JavaScript Libraries">
+									{jsLibs.map(lib => (
+										<option data-type={lib.type} value={lib.url}>
+											{lib.label}
+										</option>
+									))}
+								</optgroup>
+								<optgroup label="CSS Libraries">
+									{cssLibs.map(lib => (
+										<option data-type={lib.type} value={lib.url}>
+											{lib.label}
+										</option>
+									))}
+								</optgroup>
+							</select>
+						</div>
+
+						<h3 class="mb-0">JS</h3>
+						<p class="mt-0 help-text">
+							<Trans>Put each library in new line</Trans>
+						</p>
+
+						<p
+							style="font-size: 0.8em;"
+							class="show-when-extension opacity--70"
+						>
+							<Trans>
+								Note: You can load external scripts only from following domains:
+							</Trans>
+							localhost, https://ajax.googleapis.com, https://code.jquery.com,
+							https://cdnjs.cloudflare.com, https://unpkg.com,
+							https://maxcdn.com, https://cdn77.com,
+							https://maxcdn.bootstrapcdn.com, https://cdn.jsdelivr.net/,
+							https://rawgit.com, https://wzrd.in
+						</p>
+
+						<textarea
+							onBlur={this.textareaBlurHandler.bind(this)}
+							data-lang="js"
 							class="full-width"
-							placeholder="Type here to search libraries"
+							id="externalJsTextarea"
+							cols="30"
+							rows="5"
+							value={this.state.js}
 						/>
-					</LibraryAutoSuggest>
-				</div>
-				<div class="tar opacity--70">
-					<small>Powered by cdnjs</small>
-				</div>
-				<div style="margin:20px 0;">
-					Choose from popular libraries:{' '}
-					<select
-						name=""
-						id="js-add-library-select"
-						onChange={this.onSelectChange.bind(this)}
-					>
-						<option value="">-------</option>
-						<optgroup label="JavaScript Libraries">
-							{jsLibs.map(lib => (
-								<option data-type={lib.type} value={lib.url}>
-									{lib.label}
-								</option>
-							))}
-						</optgroup>
-						<optgroup label="CSS Libraries">
-							{cssLibs.map(lib => (
-								<option data-type={lib.type} value={lib.url}>
-									{lib.label}
-								</option>
-							))}
-						</optgroup>
-					</select>
-				</div>
 
-				<h3 class="mb-0">JS</h3>
-				<p class="mt-0 help-text">Put each library in new line</p>
-
-				<p style="font-size: 0.8em;" class="show-when-extension opacity--70">
-					Note: You can load external scripts only from following domains:
-					localhost, https://ajax.googleapis.com, https://code.jquery.com,
-					https://cdnjs.cloudflare.com, https://unpkg.com, https://maxcdn.com,
-					https://cdn77.com, https://maxcdn.bootstrapcdn.com,
-					https://cdn.jsdelivr.net/, https://rawgit.com, https://wzrd.in
-				</p>
-
-				<textarea
-					onBlur={this.textareaBlurHandler.bind(this)}
-					data-lang="js"
-					class="full-width"
-					id="externalJsTextarea"
-					cols="30"
-					rows="5"
-					value={this.state.js}
-				/>
-
-				<h3 class="mb-0">CSS</h3>
-				<p class="mt-0 help-text">Put each library in new line</p>
-				<textarea
-					onBlur={this.textareaBlurHandler.bind(this)}
-					data-lang="css"
-					class="full-width"
-					id="externalCssTextarea"
-					cols="30"
-					rows="5"
-					value={this.state.css}
-				/>
-			</div>
+						<h3 class="mb-0">CSS</h3>
+						<p class="mt-0 help-text">
+							<Trans>Put each library in new line</Trans>
+						</p>
+						<textarea
+							onBlur={this.textareaBlurHandler.bind(this)}
+							data-lang="css"
+							class="full-width"
+							id="externalCssTextarea"
+							cols="30"
+							rows="5"
+							value={this.state.css}
+						/>
+					</div>
+				)}
+			</I18n>
 		);
 	}
 }
diff --git a/src/components/Console.jsx b/src/components/Console.jsx
index 2c5c6cb..e48811e 100644
--- a/src/components/Console.jsx
+++ b/src/components/Console.jsx
@@ -1,6 +1,7 @@
 import { h, Component } from 'preact';
 import { Inspector, chromeDark } from 'react-inspector';
-import { Trans } from '@lingui/macro';
+import { Trans, t, NumberFormat } from '@lingui/macro';
+import { I18n } from '@lingui/react';
 import { PureComponent } from 'preact/compat';
 
 class LogRow extends Component {
@@ -44,62 +45,68 @@ export class Console extends PureComponent {
 		} = this.props;
 
 		return (
-			<div
-				id="consoleEl"
-				class={`console ${isConsoleOpen ? '' : 'is-minimized'}`}
-			>
-				<div id="consoleLogEl" class="console__log">
+			<I18n>
+				{({ i18n }) => (
 					<div
-						class="js-console__header  code-wrap__header"
-						title="Double click to toggle console"
-						onDblClick={onConsoleHeaderDblClick}
+						id="consoleEl"
+						class={`console ${isConsoleOpen ? '' : 'is-minimized'}`}
 					>
-						<span class="code-wrap__header-label">
-							<Trans>Console</Trans>
-							<span class="count-label">{logs.length}</span>
-						</span>
-						<div class="code-wrap__header-right-options">
-							<a
-								class="code-wrap__header-btn"
-								title="Clear console (CTRL + L)"
-								onClick={onClearConsoleBtnClick}
+						<div id="consoleLogEl" class="console__log">
+							<div
+								class="js-console__header  code-wrap__header"
+								title={i18n._(t`Double click to toggle console`)}
+								onDblClick={onConsoleHeaderDblClick}
 							>
-								<svg>
-									<use xlinkHref="#cancel-icon" />
-								</svg>
-							</a>
-							<a
-								class="code-wrap__header-btn  code-wrap__collapse-btn"
-								title="Toggle console"
-								onClick={toggleConsole}
+								<span class="code-wrap__header-label">
+									<Trans>Console</Trans>
+									<span class="count-label">
+										<NumberFormat value={logs.length} />
+									</span>
+								</span>
+								<div class="code-wrap__header-right-options">
+									<a
+										class="code-wrap__header-btn"
+										title={i18n._(t`Clear console (CTRL + L)`)}
+										onClick={onClearConsoleBtnClick}
+									>
+										<svg>
+											<use xlinkHref="#cancel-icon" />
+										</svg>
+									</a>
+									<a
+										class="code-wrap__header-btn  code-wrap__collapse-btn"
+										title={i18n._(t`Toggle console`)}
+										onClick={toggleConsole}
+									/>
+								</div>
+							</div>
+							<ul
+								class="console__items"
+								ref={el => {
+									this.logContainerEl = el;
+								}}
+							>
+								{logs.map(log => (
+									<LogRow data={log} />
+								))}
+							</ul>
+						</div>
+						<div
+							id="consolePromptEl"
+							class="console__prompt flex flex-v-center flex-shrink-0"
+						>
+							<svg width="18" height="18" fill="#346fd2">
+								<use xlinkHref="#chevron-icon" />
+							</svg>
+							<input
+								tabIndex={isConsoleOpen ? 0 : -1}
+								onKeyUp={onEvalInputKeyup}
+								class="console-exec-input"
 							/>
 						</div>
 					</div>
-					<ul
-						class="console__items"
-						ref={el => {
-							this.logContainerEl = el;
-						}}
-					>
-						{logs.map(log => (
-							<LogRow data={log} />
-						))}
-					</ul>
-				</div>
-				<div
-					id="consolePromptEl"
-					class="console__prompt flex flex-v-center flex-shrink-0"
-				>
-					<svg width="18" height="18" fill="#346fd2">
-						<use xlinkHref="#chevron-icon" />
-					</svg>
-					<input
-						tabIndex={isConsoleOpen ? 0 : -1}
-						onKeyUp={onEvalInputKeyup}
-						class="console-exec-input"
-					/>
-				</div>
-			</div>
+				)}
+			</I18n>
 		);
 	}
 }
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
index bc32188..9627249 100644
--- a/src/components/Footer.jsx
+++ b/src/components/Footer.jsx
@@ -1,5 +1,7 @@
 import { h, Component } from 'preact';
 import { Button } from './common';
+import { Trans, t } from '@lingui/macro';
+import { I18n } from '@lingui/react';
 
 class JS13K extends Component {
 	constructor(props) {
@@ -71,259 +73,265 @@ export default class Footer extends Component {
 
 	render() {
 		return (
-			<div id="footer" class="footer">
-				<div>
-					<a href="/" target="_blank" rel="noopener noreferrer">
-						<div class="logo" />
-					</a>
-					&copy;
-					<span class="web-maker-with-tag">Web Maker</span> &nbsp;&nbsp;
-					<Button
-						onClick={this.props.helpBtnClickHandler}
-						data-event-category="ui"
-						data-event-action="helpButtonClick"
-						class="footer__link  hint--rounded  hint--top-right"
-						aria-label="Help"
-					>
-						<svg
-							style="width:20px; height:20px; vertical-align:text-bottom"
-							viewBox="0 0 24 24"
-						>
-							<path d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
-						</svg>
-					</Button>
-					<Button
-						onClick={this.props.keyboardShortcutsBtnClickHandler}
-						data-event-category="ui"
-						data-event-action="keyboardShortcutButtonClick"
-						class="footer__link hint--rounded  hint--top-right hide-on-mobile"
-						aria-label="Keyboard shortcuts"
-					>
-						<svg
-							style={{
-								width: '20px',
-								height: '20px',
-								verticalAlign: 'text-bottom'
-							}}
-						>
-							<use xlinkHref="#keyboard-icon" />
-						</svg>
-					</Button>
-					<a
-						class="footer__link  hint--rounded  hint--top-right"
-						aria-label="Tweet about 'Web Maker'"
-						href="http://twitter.com/share?url=https://webmaker.app/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,frontend,playground,offline"
-						target="_blank"
-						rel="noopener noreferrer"
-					>
-						<svg
-							style={{
-								width: '20px',
-								height: '20px',
-								verticalAlign: 'text-bottom'
-							}}
-						>
-							<use xlinkHref="#twitter-icon" />
-						</svg>
-					</a>
-					<Button
-						onClick={this.props.supportDeveloperBtnClickHandler}
-						data-event-category="ui"
-						data-event-action="supportDeveloperFooterBtnClick"
-						class="footer__link  ml-1  hint--rounded  hint--top-right hide-on-mobile support-link"
-						aria-label="Support the developer by pledging some amount"
-					>
-						Donate
-					</Button>
-				</div>
+			<I18n>
+				{({ i18n }) => (
+					<div id="footer" class="footer">
+						<div>
+							<a href="/" target="_blank" rel="noopener noreferrer">
+								<div class="logo" />
+							</a>
+							&copy;
+							<span class="web-maker-with-tag">Web Maker</span> &nbsp;&nbsp;
+							<Button
+								onClick={this.props.helpBtnClickHandler}
+								data-event-category="ui"
+								data-event-action="helpButtonClick"
+								class="footer__link  hint--rounded  hint--top-right"
+								aria-label={i18n._(t`Help`)}
+							>
+								<svg
+									style="width:20px; height:20px; vertical-align:text-bottom"
+									viewBox="0 0 24 24"
+								>
+									<path d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
+								</svg>
+							</Button>
+							<Button
+								onClick={this.props.keyboardShortcutsBtnClickHandler}
+								data-event-category="ui"
+								data-event-action="keyboardShortcutButtonClick"
+								class="footer__link hint--rounded  hint--top-right hide-on-mobile"
+								aria-label={i18n._(t`Keyboard shortcuts`)}
+							>
+								<svg
+									style={{
+										width: '20px',
+										height: '20px',
+										verticalAlign: 'text-bottom'
+									}}
+								>
+									<use xlinkHref="#keyboard-icon" />
+								</svg>
+							</Button>
+							<a
+								class="footer__link  hint--rounded  hint--top-right"
+								aria-label={i18n._(t`Tweet about 'Web Maker'`)}
+								href="http://twitter.com/share?url=https://webmaker.app/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,frontend,playground,offline"
+								target="_blank"
+								rel="noopener noreferrer"
+							>
+								<svg
+									style={{
+										width: '20px',
+										height: '20px',
+										verticalAlign: 'text-bottom'
+									}}
+								>
+									<use xlinkHref="#twitter-icon" />
+								</svg>
+							</a>
+							<Button
+								onClick={this.props.supportDeveloperBtnClickHandler}
+								data-event-category="ui"
+								data-event-action="supportDeveloperFooterBtnClick"
+								class="footer__link  ml-1  hint--rounded  hint--top-right hide-on-mobile support-link"
+								aria-label={i18n._(
+									t`Support the developer by pledging some amount`
+								)}
+							>
+								<Trans>Donate</Trans>
+							</Button>
+						</div>
 
-				{this.props.prefs.isJs13kModeOn ? (
-					<div class="flex flex-v-center">
-						<JS13K
-							isOpen={this.state.isJs13kDropdownOpen}
-							codeSize={this.props.codeSize}
-							onClick={this.js13kClickHandler.bind(this)}
-							onBlur={() =>
-								setTimeout(
-									() => this.setState({ isJs13kDropdownOpen: false }),
-									300
-								)
-							}
-						/>
-						{this.state.isJs13kDropdownOpen && (
-							<div className="js13k__dropdown">
-								<button
-									class="btn"
-									style={{
-										width: '200px',
-										display: 'block',
-										marginBottom: '16px'
-									}}
-									onClick={this.props.onJs13KDownloadBtnClick}
-								>
-									Download game as zip
-								</button>
-								<a
-									class="btn"
-									rel="noopener"
-									style={{
-										width: '200px',
-										display: 'block',
-										marginBottom: '16px'
-									}}
-									href="https://pasteboard.co/"
-									target="_blank"
-								>
-									Upload Image
-								</a>
-								<button
-									class="btn"
-									style={{ width: '200px', display: 'block' }}
-									onClick={this.props.onJs13KHelpBtnClick}
-								>
-									Help
-								</button>
+						{this.props.prefs.isJs13kModeOn ? (
+							<div class="flex flex-v-center">
+								<JS13K
+									isOpen={this.state.isJs13kDropdownOpen}
+									codeSize={this.props.codeSize}
+									onClick={this.js13kClickHandler.bind(this)}
+									onBlur={() =>
+										setTimeout(
+											() => this.setState({ isJs13kDropdownOpen: false }),
+											300
+										)
+									}
+								/>
+								{this.state.isJs13kDropdownOpen && (
+									<div className="js13k__dropdown">
+										<button
+											class="btn"
+											style={{
+												width: '200px',
+												display: 'block',
+												marginBottom: '16px'
+											}}
+											onClick={this.props.onJs13KDownloadBtnClick}
+										>
+											<Trans>Download game as zip</Trans>
+										</button>
+										<a
+											class="btn"
+											rel="noopener"
+											style={{
+												width: '200px',
+												display: 'block',
+												marginBottom: '16px'
+											}}
+											href="https://pasteboard.co/"
+											target="_blank"
+										>
+											<Trans>Upload Image</Trans>
+										</a>
+										<button
+											class="btn"
+											style={{ width: '200px', display: 'block' }}
+											onClick={this.props.onJs13KHelpBtnClick}
+										>
+											<Trans>Help</Trans>
+										</button>
+									</div>
+								)}
 							</div>
-						)}
+						) : null}
+
+						<div class="footer__right">
+							<button
+								onClick={this.props.saveHtmlBtnClickHandler}
+								id="saveHtmlBtn"
+								class="mode-btn  hint--rounded  hint--top-left hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Save as HTML file`)}
+							>
+								<svg viewBox="0 0 24 24">
+									<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
+								</svg>
+							</button>
+							<svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
+								<symbol id="codepen-logo" viewBox="0 0 120 120">
+									<path
+										class="outer-ring"
+										d="M60.048 0C26.884 0 0 26.9 0 60.048s26.884 60 60 60.047c33.163 0 60.047-26.883 60.047-60.047 S93.211 0 60 0z M60.048 110.233c-27.673 0-50.186-22.514-50.186-50.186S32.375 9.9 60 9.9 c27.672 0 50.2 22.5 50.2 50.186S87.72 110.2 60 110.233z"
+									/>
+									<path
+										class="inner-box"
+										d="M97.147 48.319c-0.007-0.047-0.019-0.092-0.026-0.139c-0.016-0.09-0.032-0.18-0.056-0.268 c-0.014-0.053-0.033-0.104-0.05-0.154c-0.025-0.078-0.051-0.156-0.082-0.232c-0.021-0.053-0.047-0.105-0.071-0.156 c-0.033-0.072-0.068-0.143-0.108-0.211c-0.029-0.051-0.061-0.1-0.091-0.148c-0.043-0.066-0.087-0.131-0.135-0.193 c-0.035-0.047-0.072-0.094-0.109-0.139c-0.051-0.059-0.104-0.117-0.159-0.172c-0.042-0.043-0.083-0.086-0.127-0.125 c-0.059-0.053-0.119-0.104-0.181-0.152c-0.048-0.037-0.095-0.074-0.145-0.109c-0.019-0.012-0.035-0.027-0.053-0.039L61.817 23.5 c-1.072-0.715-2.468-0.715-3.54 0L24.34 46.081c-0.018 0.012-0.034 0.027-0.053 0.039c-0.05 0.035-0.097 0.072-0.144 0.1 c-0.062 0.049-0.123 0.1-0.181 0.152c-0.045 0.039-0.086 0.082-0.128 0.125c-0.056 0.055-0.108 0.113-0.158 0.2 c-0.038 0.045-0.075 0.092-0.11 0.139c-0.047 0.062-0.092 0.127-0.134 0.193c-0.032 0.049-0.062 0.098-0.092 0.1 c-0.039 0.068-0.074 0.139-0.108 0.211c-0.024 0.051-0.05 0.104-0.071 0.156c-0.031 0.076-0.057 0.154-0.082 0.2 c-0.017 0.051-0.035 0.102-0.05 0.154c-0.023 0.088-0.039 0.178-0.056 0.268c-0.008 0.047-0.02 0.092-0.025 0.1 c-0.019 0.137-0.029 0.275-0.029 0.416V71.36c0 0.1 0 0.3 0 0.418c0.006 0 0 0.1 0 0.1 c0.017 0.1 0 0.2 0.1 0.268c0.015 0.1 0 0.1 0.1 0.154c0.025 0.1 0.1 0.2 0.1 0.2 c0.021 0.1 0 0.1 0.1 0.154c0.034 0.1 0.1 0.1 0.1 0.213c0.029 0 0.1 0.1 0.1 0.1 c0.042 0.1 0.1 0.1 0.1 0.193c0.035 0 0.1 0.1 0.1 0.139c0.05 0.1 0.1 0.1 0.2 0.2 c0.042 0 0.1 0.1 0.1 0.125c0.058 0.1 0.1 0.1 0.2 0.152c0.047 0 0.1 0.1 0.1 0.1 c0.019 0 0 0 0.1 0.039L58.277 96.64c0.536 0.4 1.2 0.5 1.8 0.537c0.616 0 1.233-0.18 1.77-0.537 l33.938-22.625c0.018-0.012 0.034-0.027 0.053-0.039c0.05-0.035 0.097-0.072 0.145-0.109c0.062-0.049 0.122-0.1 0.181-0.152 c0.044-0.039 0.085-0.082 0.127-0.125c0.056-0.055 0.108-0.113 0.159-0.172c0.037-0.045 0.074-0.09 0.109-0.139 c0.048-0.062 0.092-0.127 0.135-0.193c0.03-0.049 0.062-0.098 0.091-0.146c0.04-0.07 0.075-0.141 0.108-0.213 c0.024-0.051 0.05-0.102 0.071-0.154c0.031-0.078 0.057-0.156 0.082-0.234c0.017-0.051 0.036-0.102 0.05-0.154 c0.023-0.088 0.04-0.178 0.056-0.268c0.008-0.045 0.02-0.092 0.026-0.137c0.018-0.139 0.028-0.277 0.028-0.418V48.735 C97.176 48.6 97.2 48.5 97.1 48.319z M63.238 32.073l25.001 16.666L77.072 56.21l-13.834-9.254V32.073z M56.856 32.1 v14.883L43.023 56.21l-11.168-7.471L56.856 32.073z M29.301 54.708l7.983 5.34l-7.983 5.34V54.708z M56.856 88.022L31.855 71.4 l11.168-7.469l13.833 9.252V88.022z M60.048 67.597l-11.286-7.549l11.286-7.549l11.285 7.549L60.048 67.597z M63.238 88.022V73.14 l13.834-9.252l11.167 7.469L63.238 88.022z M90.794 65.388l-7.982-5.34l7.982-5.34V65.388z"
+									/>
+								</symbol>
+							</svg>
+
+							<button
+								onClick={this.props.codepenBtnClickHandler}
+								id="codepenBtn"
+								class="mode-btn  hint--rounded  hint--top-left  hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Edit on CodePen`)}
+							>
+								<svg>
+									<use xlinkHref="#codepen-logo" />
+								</svg>
+							</button>
+
+							<button
+								id="screenshotBtn"
+								class="mode-btn  hint--rounded  hint--top-left show-when-extension"
+								onClick={this.props.screenshotBtnClickHandler}
+								aria-label={i18n._(t`Take screenshot of preview`)}
+							>
+								<svg style="width:24px;height:24px" viewBox="0 0 24 24">
+									<path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" />
+								</svg>
+							</button>
+
+							<div class="footer__separator hide-on-mobile" />
+
+							<button
+								onClick={this.layoutBtnClickhandler.bind(this, 1)}
+								id="layoutBtn1"
+								class="mode-btn hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Switch to layout with preview on right`)}
+							>
+								<svg viewBox="0 0 100 100" style="transform:rotate(-90deg)">
+									<use xlinkHref="#mode-icon" />
+								</svg>
+							</button>
+							<button
+								onClick={this.layoutBtnClickhandler.bind(this, 2)}
+								id="layoutBtn2"
+								class="mode-btn hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Switch to layout with preview on bottom`)}
+							>
+								<svg viewBox="0 0 100 100">
+									<use xlinkHref="#mode-icon" />
+								</svg>
+							</button>
+							<button
+								onClick={this.layoutBtnClickhandler.bind(this, 3)}
+								id="layoutBtn3"
+								class="mode-btn hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Switch to layout with preview on left`)}
+							>
+								<svg viewBox="0 0 100 100" style="transform:rotate(90deg)">
+									<use xlinkHref="#mode-icon" />
+								</svg>
+							</button>
+							<button
+								onClick={this.layoutBtnClickhandler.bind(this, 5)}
+								id="layoutBtn5"
+								class="mode-btn hide-on-mobile hide-in-file-mode"
+								aria-label={i18n._(t`Switch to layout with all vertical panes`)}
+							>
+								<svg viewBox="0 0 100 100">
+									<use xlinkHref="#vertical-mode-icon" />
+								</svg>
+							</button>
+							<button
+								onClick={this.layoutBtnClickhandler.bind(this, 4)}
+								id="layoutBtn4"
+								class="mode-btn hint--top-left hint--rounded hide-in-file-mode hide-on-mobile"
+								aria-label={i18n._(t`Switch to full screen preview`)}
+							>
+								<svg viewBox="0 0 100 100">
+									<rect x="0" y="0" width="100" height="100" />
+								</svg>
+							</button>
+							<button
+								class="mode-btn hint--top-left hint--rounded hide-on-mobile"
+								aria-label={i18n._(t`Detach preview`)}
+								onClick={this.props.detachedPreviewBtnHandler}
+							>
+								<svg viewBox="0 0 24 24">
+									<path d="M22,17V7H6V17H22M22,5A2,2 0 0,1 24,7V17C24,18.11 23.1,19 22,19H16V21H18V23H10V21H12V19H6C4.89,19 4,18.11 4,17V7A2,2 0 0,1 6,5H22M2,3V15H0V3A2,2 0 0,1 2,1H20V3H2Z" />
+								</svg>
+							</button>
+
+							<div class="footer__separator" />
+
+							<button
+								onClick={this.props.notificationsBtnClickHandler}
+								id="notificationsBtn"
+								class={`notifications-btn  mode-btn  hint--top-left  hint--rounded ${
+									this.props.hasUnseenChangelog ? 'has-new' : ''
+								}`}
+								aria-label={i18n._(t`See changelog`)}
+							>
+								<svg viewBox="0 0 24 24">
+									<path d="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />
+								</svg>
+								<span class="notifications-btn__dot" />
+							</button>
+							<Button
+								onClick={this.props.settingsBtnClickHandler}
+								data-event-category="ui"
+								data-event-action="settingsBtnClick"
+								class="mode-btn  hint--top-left  hint--rounded"
+								aria-label={i18n._(t`Settings`)}
+							>
+								<svg>
+									<use xlinkHref="#settings-icon" />
+								</svg>
+							</Button>
+						</div>
 					</div>
-				) : null}
-
-				<div class="footer__right">
-					<button
-						onClick={this.props.saveHtmlBtnClickHandler}
-						id="saveHtmlBtn"
-						class="mode-btn  hint--rounded  hint--top-left hide-on-mobile hide-in-file-mode"
-						aria-label="Save as HTML file"
-					>
-						<svg viewBox="0 0 24 24">
-							<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
-						</svg>
-					</button>
-					<svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
-						<symbol id="codepen-logo" viewBox="0 0 120 120">
-							<path
-								class="outer-ring"
-								d="M60.048 0C26.884 0 0 26.9 0 60.048s26.884 60 60 60.047c33.163 0 60.047-26.883 60.047-60.047 S93.211 0 60 0z M60.048 110.233c-27.673 0-50.186-22.514-50.186-50.186S32.375 9.9 60 9.9 c27.672 0 50.2 22.5 50.2 50.186S87.72 110.2 60 110.233z"
-							/>
-							<path
-								class="inner-box"
-								d="M97.147 48.319c-0.007-0.047-0.019-0.092-0.026-0.139c-0.016-0.09-0.032-0.18-0.056-0.268 c-0.014-0.053-0.033-0.104-0.05-0.154c-0.025-0.078-0.051-0.156-0.082-0.232c-0.021-0.053-0.047-0.105-0.071-0.156 c-0.033-0.072-0.068-0.143-0.108-0.211c-0.029-0.051-0.061-0.1-0.091-0.148c-0.043-0.066-0.087-0.131-0.135-0.193 c-0.035-0.047-0.072-0.094-0.109-0.139c-0.051-0.059-0.104-0.117-0.159-0.172c-0.042-0.043-0.083-0.086-0.127-0.125 c-0.059-0.053-0.119-0.104-0.181-0.152c-0.048-0.037-0.095-0.074-0.145-0.109c-0.019-0.012-0.035-0.027-0.053-0.039L61.817 23.5 c-1.072-0.715-2.468-0.715-3.54 0L24.34 46.081c-0.018 0.012-0.034 0.027-0.053 0.039c-0.05 0.035-0.097 0.072-0.144 0.1 c-0.062 0.049-0.123 0.1-0.181 0.152c-0.045 0.039-0.086 0.082-0.128 0.125c-0.056 0.055-0.108 0.113-0.158 0.2 c-0.038 0.045-0.075 0.092-0.11 0.139c-0.047 0.062-0.092 0.127-0.134 0.193c-0.032 0.049-0.062 0.098-0.092 0.1 c-0.039 0.068-0.074 0.139-0.108 0.211c-0.024 0.051-0.05 0.104-0.071 0.156c-0.031 0.076-0.057 0.154-0.082 0.2 c-0.017 0.051-0.035 0.102-0.05 0.154c-0.023 0.088-0.039 0.178-0.056 0.268c-0.008 0.047-0.02 0.092-0.025 0.1 c-0.019 0.137-0.029 0.275-0.029 0.416V71.36c0 0.1 0 0.3 0 0.418c0.006 0 0 0.1 0 0.1 c0.017 0.1 0 0.2 0.1 0.268c0.015 0.1 0 0.1 0.1 0.154c0.025 0.1 0.1 0.2 0.1 0.2 c0.021 0.1 0 0.1 0.1 0.154c0.034 0.1 0.1 0.1 0.1 0.213c0.029 0 0.1 0.1 0.1 0.1 c0.042 0.1 0.1 0.1 0.1 0.193c0.035 0 0.1 0.1 0.1 0.139c0.05 0.1 0.1 0.1 0.2 0.2 c0.042 0 0.1 0.1 0.1 0.125c0.058 0.1 0.1 0.1 0.2 0.152c0.047 0 0.1 0.1 0.1 0.1 c0.019 0 0 0 0.1 0.039L58.277 96.64c0.536 0.4 1.2 0.5 1.8 0.537c0.616 0 1.233-0.18 1.77-0.537 l33.938-22.625c0.018-0.012 0.034-0.027 0.053-0.039c0.05-0.035 0.097-0.072 0.145-0.109c0.062-0.049 0.122-0.1 0.181-0.152 c0.044-0.039 0.085-0.082 0.127-0.125c0.056-0.055 0.108-0.113 0.159-0.172c0.037-0.045 0.074-0.09 0.109-0.139 c0.048-0.062 0.092-0.127 0.135-0.193c0.03-0.049 0.062-0.098 0.091-0.146c0.04-0.07 0.075-0.141 0.108-0.213 c0.024-0.051 0.05-0.102 0.071-0.154c0.031-0.078 0.057-0.156 0.082-0.234c0.017-0.051 0.036-0.102 0.05-0.154 c0.023-0.088 0.04-0.178 0.056-0.268c0.008-0.045 0.02-0.092 0.026-0.137c0.018-0.139 0.028-0.277 0.028-0.418V48.735 C97.176 48.6 97.2 48.5 97.1 48.319z M63.238 32.073l25.001 16.666L77.072 56.21l-13.834-9.254V32.073z M56.856 32.1 v14.883L43.023 56.21l-11.168-7.471L56.856 32.073z M29.301 54.708l7.983 5.34l-7.983 5.34V54.708z M56.856 88.022L31.855 71.4 l11.168-7.469l13.833 9.252V88.022z M60.048 67.597l-11.286-7.549l11.286-7.549l11.285 7.549L60.048 67.597z M63.238 88.022V73.14 l13.834-9.252l11.167 7.469L63.238 88.022z M90.794 65.388l-7.982-5.34l7.982-5.34V65.388z"
-							/>
-						</symbol>
-					</svg>
-
-					<button
-						onClick={this.props.codepenBtnClickHandler}
-						id="codepenBtn"
-						class="mode-btn  hint--rounded  hint--top-left  hide-on-mobile hide-in-file-mode"
-						aria-label="Edit on CodePen"
-					>
-						<svg>
-							<use xlinkHref="#codepen-logo" />
-						</svg>
-					</button>
-
-					<button
-						id="screenshotBtn"
-						class="mode-btn  hint--rounded  hint--top-left show-when-extension"
-						onClick={this.props.screenshotBtnClickHandler}
-						aria-label="Take screenshot of preview"
-					>
-						<svg style="width:24px;height:24px" viewBox="0 0 24 24">
-							<path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" />
-						</svg>
-					</button>
-
-					<div class="footer__separator hide-on-mobile" />
-
-					<button
-						onClick={this.layoutBtnClickhandler.bind(this, 1)}
-						id="layoutBtn1"
-						class="mode-btn hide-on-mobile hide-in-file-mode"
-						aria-label="Switch to layout with preview on right"
-					>
-						<svg viewBox="0 0 100 100" style="transform:rotate(-90deg)">
-							<use xlinkHref="#mode-icon" />
-						</svg>
-					</button>
-					<button
-						onClick={this.layoutBtnClickhandler.bind(this, 2)}
-						id="layoutBtn2"
-						class="mode-btn hide-on-mobile hide-in-file-mode"
-						aria-label="Switch to layout with preview on bottom"
-					>
-						<svg viewBox="0 0 100 100">
-							<use xlinkHref="#mode-icon" />
-						</svg>
-					</button>
-					<button
-						onClick={this.layoutBtnClickhandler.bind(this, 3)}
-						id="layoutBtn3"
-						class="mode-btn hide-on-mobile hide-in-file-mode"
-						aria-label="Switch to layout with preview on left"
-					>
-						<svg viewBox="0 0 100 100" style="transform:rotate(90deg)">
-							<use xlinkHref="#mode-icon" />
-						</svg>
-					</button>
-					<button
-						onClick={this.layoutBtnClickhandler.bind(this, 5)}
-						id="layoutBtn5"
-						class="mode-btn hide-on-mobile hide-in-file-mode"
-						aria-label="Switch to layout with all vertical panes"
-					>
-						<svg viewBox="0 0 100 100">
-							<use xlinkHref="#vertical-mode-icon" />
-						</svg>
-					</button>
-					<button
-						onClick={this.layoutBtnClickhandler.bind(this, 4)}
-						id="layoutBtn4"
-						class="mode-btn hint--top-left hint--rounded hide-in-file-mode hide-on-mobile"
-						aria-label="Switch to full screen preview"
-					>
-						<svg viewBox="0 0 100 100">
-							<rect x="0" y="0" width="100" height="100" />
-						</svg>
-					</button>
-					<button
-						class="mode-btn hint--top-left hint--rounded hide-on-mobile"
-						aria-label="Detach Preview"
-						onClick={this.props.detachedPreviewBtnHandler}
-					>
-						<svg viewBox="0 0 24 24">
-							<path d="M22,17V7H6V17H22M22,5A2,2 0 0,1 24,7V17C24,18.11 23.1,19 22,19H16V21H18V23H10V21H12V19H6C4.89,19 4,18.11 4,17V7A2,2 0 0,1 6,5H22M2,3V15H0V3A2,2 0 0,1 2,1H20V3H2Z" />
-						</svg>
-					</button>
-
-					<div class="footer__separator" />
-
-					<button
-						onClick={this.props.notificationsBtnClickHandler}
-						id="notificationsBtn"
-						class={`notifications-btn  mode-btn  hint--top-left  hint--rounded ${
-							this.props.hasUnseenChangelog ? 'has-new' : ''
-						}`}
-						aria-label="See Changelog"
-					>
-						<svg viewBox="0 0 24 24">
-							<path d="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />
-						</svg>
-						<span class="notifications-btn__dot" />
-					</button>
-					<Button
-						onClick={this.props.settingsBtnClickHandler}
-						data-event-category="ui"
-						data-event-action="settingsBtnClick"
-						class="mode-btn  hint--top-left  hint--rounded"
-						aria-label="Settings"
-					>
-						<svg>
-							<use xlinkHref="#settings-icon" />
-						</svg>
-					</Button>
-				</div>
-			</div>
+				)}
+			</I18n>
 		);
 	}
 }
diff --git a/src/components/SavedItemPane.jsx b/src/components/SavedItemPane.jsx
index e0793c7..8bb11d7 100644
--- a/src/components/SavedItemPane.jsx
+++ b/src/components/SavedItemPane.jsx
@@ -1,10 +1,9 @@
 import { h, Component } from 'preact';
 import { log } from '../utils';
 import { trackEvent } from '../analytics';
-import { itemService } from '../itemService';
-import { alertsService } from '../notifications';
-import { deferred } from '../deferred';
 import { ItemTile } from './ItemTile';
+import { Trans, NumberFormat, t } from '@lingui/macro';
+import { I18n } from '@lingui/react';
 
 export default class SavedItemPane extends Component {
 	constructor(props) {
@@ -113,7 +112,9 @@ export default class SavedItemPane extends Component {
 			} catch (exception) {
 				log(exception);
 				alert(
-					'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.'
+					i18n._(
+						t`'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.`
+					)
 				);
 			}
 		});
@@ -154,69 +155,92 @@ export default class SavedItemPane extends Component {
 		{ filteredItems = this.state.items, items = [] }
 	) {
 		return (
-			<div
-				id="js-saved-items-pane"
-				class={`saved-items-pane ${isOpen ? 'is-open' : ''}`}
-				onKeyDown={this.keyDownHandler.bind(this)}
-				aria-hidden={isOpen}
-			>
-				<button
-					onClick={this.onCloseIntent.bind(this)}
-					class="btn  saved-items-pane__close-btn"
-					id="js-saved-items-pane-close-btn"
-					aria-label="Close saved creations pane"
-				>
-					X
-				</button>
-				<div class="flex flex-v-center" style="justify-content: space-between;">
-					<h3>My Library ({filteredItems.length})</h3>
-
-					<div>
+			<I18n>
+				{({ i18n }) => (
+					<div
+						id="js-saved-items-pane"
+						class={`saved-items-pane ${isOpen ? 'is-open' : ''}`}
+						onKeyDown={this.keyDownHandler.bind(this)}
+						aria-hidden={isOpen}
+					>
 						<button
-							onClick={exportBtnClickHandler}
-							class="btn--dark hint--bottom-left hint--rounded hint--medium"
-							aria-label="Export all your creations into a single importable file."
+							onClick={this.onCloseIntent.bind(this)}
+							class="btn  saved-items-pane__close-btn"
+							id="js-saved-items-pane-close-btn"
+							aria-label={i18n._(t`Close saved creations pane`)}
 						>
-							Export
+							X
 						</button>
-						<button
-							onClick={this.importBtnClickHandler.bind(this)}
-							class="btn--dark hint--bottom-left hint--rounded hint--medium"
-							aria-label="Import your creations. Only the file that you export through the 'Export' button can be imported."
+						<div
+							class="flex flex-v-center"
+							style="justify-content: space-between;"
 						>
-							Import
-						</button>
-					</div>
-				</div>
-				<input
-					autocomplete="off"
-					type="search"
-					id="searchInput"
-					class="search-input"
-					onInput={this.searchInputHandler.bind(this)}
-					placeholder="Search your creations here..."
-				/>
+							<h3>
+								<Trans>My Library ({filteredItems.length})</Trans>
+							</h3>
 
-				<div id="js-saved-items-wrap" class="saved-items-pane__container">
-					{!filteredItems.length && items.length ? (
-						<div class="mt-1">No match found.</div>
-					) : null}
-					{filteredItems.map(item => (
-						<ItemTile
-							item={item}
-							onClick={this.itemClickHandler.bind(this, item)}
-							onForkBtnClick={this.itemForkBtnClickHandler.bind(this, item)}
-							onRemoveBtnClick={this.itemRemoveBtnClickHandler.bind(this, item)}
-						/>
-					))}
-					{!items.length ? (
-						<div class="tac">
-							<h2 class="opacity--30">Nothing saved here.</h2>
-							<img style="max-width: 80%; opacity:0.4" src="assets/empty.svg" />
+							<div>
+								<button
+									onClick={exportBtnClickHandler}
+									class="btn--dark hint--bottom-left hint--rounded hint--medium"
+									aria-label={i18n._(
+										t`Export all your creations into a single importable file.`
+									)}
+								>
+									<Trans>Export</Trans>
+								</button>
+								<button
+									onClick={this.importBtnClickHandler.bind(this)}
+									class="btn--dark hint--bottom-left hint--rounded hint--medium"
+									aria-label={i18n._(
+										t`Import your creations. Only the file that you export through the 'Export' button can be imported.`
+									)}
+								>
+									<Trans>Import</Trans>
+								</button>
+							</div>
 						</div>
-					) : null}
-				</div>
-			</div>
+						<input
+							autocomplete="off"
+							type="search"
+							id="searchInput"
+							class="search-input"
+							onInput={this.searchInputHandler.bind(this)}
+							placeholder={i18n._(t`Search your creations here...`)}
+						/>
+
+						<div id="js-saved-items-wrap" class="saved-items-pane__container">
+							{!filteredItems.length && items.length ? (
+								<div class="mt-1">
+									<Trans>No match found.</Trans>
+								</div>
+							) : null}
+							{filteredItems.map(item => (
+								<ItemTile
+									item={item}
+									onClick={this.itemClickHandler.bind(this, item)}
+									onForkBtnClick={this.itemForkBtnClickHandler.bind(this, item)}
+									onRemoveBtnClick={this.itemRemoveBtnClickHandler.bind(
+										this,
+										item
+									)}
+								/>
+							))}
+							{!items.length ? (
+								<div class="tac">
+									<h2 class="opacity--30">
+										<Trans>Nothing saved here.</Trans>
+									</h2>
+									<img
+										style="max-width: 80%; opacity:0.4"
+										src="assets/empty.svg"
+									/>
+								</div>
+							) : null}
+						</div>
+					</div>
+				)}
+			</I18n>
 		);
 	}
 }
diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx
index 433f9bd..87d1db5 100644
--- a/src/components/Settings.jsx
+++ b/src/components/Settings.jsx
@@ -378,24 +378,24 @@ export default class Settings extends Component {
 								stopped.
 							</HelpText>
 						</div>
-						{/*
-							<Divider />
-							
-							<div>
+
+						<Divider />
+
+						<div>
 							<label class="line">
-							Language
-							<select
-							value={prefs.lang}
-							onChange={e => this.updateSetting(e, 'lang')}
-							>
-							<option value="en">English</option>
-							<option value="hi">Hindi</option>
-							<option value="sa">Sanskrit</option>
-							<option value="es">Spanish</option>
-							</select>
+								Language
+								<select
+									value={prefs.lang}
+									onChange={e => this.updateSetting(e, 'lang')}
+								>
+									<option value="en">English</option>
+									<option value="hi">हिंदी</option>
+									<option value="sa">Sanskrit</option>
+									<option value="es">Español (España)</option>
+									<option value="zh-Hans">中文(简体)</option>
+								</select>
 							</label>
-							</div>
-						*/}
+						</div>
 					</TabPanel>
 				</Tabs>
 			</div>