diff --git a/ext/src/_locales/no/messages.json b/ext/src/_locales/no/messages.json
new file mode 100644
index 0000000..c5ff996
--- /dev/null
+++ b/ext/src/_locales/no/messages.json
@@ -0,0 +1,405 @@
+{
+ "extensionName": {
+ "message": "EXTENSION_NAME"
+ , "description": "Name of the extension and the native receiver selector window title."
+ }
+ , "extensionDescription": {
+ "message": "Skrur på Chromecast for å caste apper på nettet (som Netflix eller BBC iPlayer), HTML5 video og skjerm/fane-deling"
+ , "description": "Description of the extension shown in the add-ons manager."
+ }
+
+
+ , "popupMediaTypeApp": {
+ "message": "denne sidens applikasjon"
+ , "description": "Receiver selector media type text for current site's sender application."
+ }
+ , "popupMediaTypeAppNotFound": {
+ "message": "denne sidens applikasjon (ikke funnet)"
+ , "description": "Receiver selector media type text for current site's sender application if none found."
+ }
+ , "popupMediaTypeAppMedia": {
+ "message": "dette medium"
+ , "description": "Receiver selector media type text for media casting."
+ }
+ , "popupMediaTypeTab": {
+ "message": "Fane"
+ , "description": "Receiver selector media type text for current tab."
+ }
+ , "popupMediaTypeScreen": {
+ "message": "Skjerm"
+ , "description": "Receiver selector media type text for screen."
+ }
+ , "popupMediaTypeFile": {
+ "message": "Søk..."
+ , "description": "Receiver selector media type text for opening a file selector dialog."
+ }
+
+ , "popupMediaSelectCastLabel": {
+ "message": "Cast"
+ , "description": "(Cast) to:"
+ }
+ , "popupMediaSelectToLabel": {
+ "message": "til:"
+ , "description": "Cast (to:)"
+ }
+ , "popupNoReceiversFound": {
+ "message": "Ingen mottagere funnet"
+ , "description": "Message displayed in the receiver selector if there are no available receivers."
+ }
+ , "popupCastButtonTitle": {
+ "message": "Cast"
+ , "description": "Button text for each receiver entry in the receiver selector."
+ }
+ , "popupCastingButtonTitle": {
+ "message": "Caster$ellipsis$"
+ , "description": "Button text while establishing a session in the receiver selector. Ellipsis cycles (. → .. → ...) as loading indicator."
+ , "placeholders": {
+ "ellipsis": {
+ "content": "$1"
+ , "example": "..."
+ }
+ }
+ }
+ , "popupStopButtonTitle": {
+ "message": "Stopp"
+ , "description": "Alternate action button text displayed instead of popupCastButtonTitle."
+ }
+
+
+ , "contextCast": {
+ "message": "Cast..."
+ , "description": "Main context menu item title. Ellipsis indicates additional information required as it triggers opening of receiver selector."
+ }
+
+ , "contextAddToWhitelist": {
+ "message": "Legg til i Whitelist"
+ , "description": "Top-level whitelist context menu item title."
+ }
+ , "contextAddToWhitelistRecommended": {
+ "message": "Legg til $matchPattern$ (anbefalt)"
+ , "description": "Context menu item title for recomended match pattern."
+ , "placeholders": {
+ "matchPattern": {
+ "content": "$1"
+ , "example": "https://example.com/*"
+ }
+ }
+ }
+ , "contextAddToWhitelistAdvancedAdd": {
+ "message": "Legg til $matchPattern$"
+ , "description": "Context menu item title for all other match patterns."
+ , "placeholders": {
+ "matchPattern": {
+ "content": "$1"
+ , "example": "*://*.example.com/*"
+ }
+ }
+ }
+
+
+ , "mediaOverlayTitle": {
+ "message": "Spiller på $receiverName$"
+ , "description": "Main title for overlay displayed on media elements whilst casting."
+ , "placeholders": {
+ "receiverName": {
+ "content": "$1"
+ , "example": "Living Room TV"
+ }
+ }
+ }
+
+ , "optionsBridgeLoading": {
+ "message": "Laster bro-info"
+ , "description": "Loading placeholder text for bridge section on options page."
+ }
+ , "optionsBridgeFoundStatusTitle": {
+ "message": "Bro funnet"
+ , "description": "Bridge OK status title text."
+ }
+ , "optionsBridgeIssueStatusTitle": {
+ "message": "Problem med bro"
+ , "description": "Bridge error status title text."
+ }
+ , "optionsBridgeNotFoundStatusTitle": {
+ "message": "Bro ikke netfun"
+ , "description": "Bridge missing status title text."
+ }
+ , "optionsBridgeNotFoundStatusText": {
+ "message": "Prøv å last ned nyeste versjon"
+ , "description": "Bridge not found additional description text"
+ }
+
+ , "optionsBridgeStatsName": {
+ "message": "Navn:"
+ , "description": "Bridge stats name row title."
+ }
+ , "optionsBridgeStatsVersion": {
+ "message": "Versjon:"
+ , "description": "Bridge stats version row title."
+ }
+ , "optionsBridgeStatsExpectedVersion": {
+ "message": "Forventet versjon:"
+ , "description": "Bridge stats expected version row title."
+ }
+ , "optionsBridgeStatsCompatibility": {
+ "message": "Kompatibilitet:"
+ , "description": "Bridge stats compatibility row title."
+ }
+ , "optionsBridgeStatsRecommendedAction": {
+ "message": "Anbefalt handling:"
+ , "description": "Bridge stats recommended action row title."
+ }
+ , "optionsBridgeCompatible": {
+ "message": "Kompatibel"
+ , "description": "Compatibility status is definitely compatible."
+ }
+ , "optionsBridgeLikelyCompatible": {
+ "message": "Sannsynlig kompatibel"
+ , "description": "Compatibility status is probably compatible."
+ }
+ , "optionsBridgeIncompatible": {
+ "message": "Ukompatibel"
+ , "description": "Compatibility status is definitely incompatible."
+ }
+ , "optionsBridgeOlderAction": {
+ "message": "Broversjon er eldre enn forventet, prøv å oppgradere bro til nyeste versjon"
+ , "description": "Recommended action for when the installed bridge version is older than the installed extension version."
+ }
+ , "optionsBridgeNewerAction": {
+ "message": "Broversjon er nyere enn forventet, prøv å nedgradere bro til en eldre versjon"
+ , "description": "Recommended action for when the installed bridge version is newer than the installed extension version."
+ }
+ , "optionsBridgeNoAction": {
+ "message": "Ingen handling nødvendig."
+ , "description": "Recommended action for when both bridge and extension versions are compatible or likely compatible."
+ }
+ , "optionsBridgeUpdateCheck": {
+ "message": "Sjekker etter Oppdateringer"
+ , "description": "Update check button title."
+ }
+ , "optionsBridgeUpdateChecking": {
+ "message": "Sjekker etter Oppdateringer$ellipsis$"
+ , "description": "Update check button title while in progress. Ellipsis cycles (. → .. → ...) as loading indicator."
+ , "placeholders": {
+ "ellipsis": {
+ "content": "$1"
+ , "example": ".."
+ }
+ }
+ }
+ , "optionsBridgeUpdateStatusNoUpdates": {
+ "message": "Ingen oppdateringer tilgjengelig"
+ , "description": "Update status if no updates are found."
+ }
+ , "optionsBridgeUpdateStatusError": {
+ "message": "Klarte ikke finne oppdateringer"
+ , "description": "Update status if an error was encountered checking for updates."
+ }
+ , "optionsBridgeUpdateAvailable": {
+ "message": "En ny oppdatering er tilgjengelig:"
+ , "description": "Update status if an update was found."
+ }
+ , "optionsBridgeUpdate": {
+ "message": "Oppdater nå..."
+ , "description": "Update now button title. Ellipsis indicates additional information as it triggers an update window popup."
+ }
+
+ , "optionsBridgeBackupEnabled": {
+ "message": "Skru på backup daemon tilkobling på $hostPort$"
+ , "description": "Backup daemon checkbox label. Host/port inputs are inserted inline at the hostPort substitution."
+ , "placeholders": {
+ "hostPort": {
+ "content": "$1"
+ }
+ }
+ }
+ , "optionsBridgeBackupEnabledDescription": {
+ "message": "Hvis den vanlige bro-tilkoblingen mislykkes, prøv å koble til en bro som kjører i daemon-modus"
+ , "description": "Backup daemon checkbox description."
+ }
+
+ , "optionsMediaCategoryName": {
+ "message": "Media-casting"
+ , "description": "Options page media casting category title."
+ }
+ , "optionsMediaCategoryDescription": {
+ "message": "HTML5 video/lyd-casting"
+ , "description": "Options page media casting category description."
+ }
+ , "optionsMediaEnabled": {
+ "message": "Skru på media-casting"
+ , "description": "Media casting enabled checkbox label."
+ }
+ , "optionsMediaOverlayEnabled": {
+ "message": "Skru på element-overlegg (eksperimentell)"
+ , "description": "Media element overlay checkbox label."
+ }
+ , "optionsMediaOverlayEnabledTemp": {
+ "message": "Skru på element-overlegg (eksperimentell)"
+ , "description": "Experimental-labelled version of above."
+ }
+ , "optionsMediaOverlayEnabledDescription": {
+ "message": "mediaelementer "
+ , "description": "Media element overlay option description."
+ }
+ , "optionsMediaSyncElement": {
+ "message": "Synkroniser mottager med mediaelement"
+ , "description": "Media casting sync checkbox label."
+ }
+ , "optionsMediaSyncElementDescription": {
+ "message": "Synkroniser tilstand (playback, volum, undertekster, etc...) mellom mediaelement og mottagerdingsen."
+ , "description": "Media casting sync option description."
+ }
+ , "optionsMediaStopOnUnload": {
+ "message": "Stop spilling på mottager når siden lukkes"
+ , "description": "Media stop on unload checkbox label."
+ }
+
+ , "optionsLocalMediaCategoryName": {
+ "message": "Lokal media-casting"
+ , "description": "Options page local media category title."
+ }
+ , "optionsLocalMediaCategoryDescription": {
+ "message": "HTTP server startet via bro-appen til å steame lokale mediafiler til mottageren"
+ , "description": "Options page local media category description."
+ }
+ , "optionsLocalMediaEnabled": {
+ "message": "Skru på casting av lokal media"
+ , "description": "Local media enabled checkbox label."
+ }
+ , "optionsLocalMediaServerPort": {
+ "message": "HTTP-server port:"
+ , "description": "HTTP server port input label."
+ }
+
+ , "optionsReceiverSelectorCategoryName": {
+ "message": "Velg mottager"
+ , "description": "Options page receiver selector category title."
+ }
+ , "optionsReceiverSelectorCategoryDescription": {
+ "message": "Grensesnitt for valg av mottager"
+ , "description": "Options page receiver selector category description."
+ }
+ , "optionsReceiverSelectorType": {
+ "message": "Type:"
+ , "description": "Receiver selector type option label."
+ }
+ , "optionsReceiverSelectorTypeBrowser": {
+ "message": "Nettleser"
+ , "description": "Receiver selector type browser radio option label."
+ }
+ , "optionsReceiverSelectorTypeNative": {
+ "message": "Native"
+ , "description": "Receiver selector type native radio option label."
+ }
+ , "optionsReceiverSelectorWaitForConnection": {
+ "message": "Vent på tilkobling"
+ , "description": "Receiver selector wait for connection option checkbox label."
+ }
+ , "optionsReceiverSelectorWaitForConnectionDescription": {
+ "message": "Hold mottagervelgeren åpen til sessjonen er etablert eller tilkoblingen mislykkes."
+ , "description": "Receiver selector wait for connection option description."
+ }
+ , "optionsReceiverSelectorCloseIfFocusLost": {
+ "message": "Lukk når fokus mistes"
+ , "description": "Receiver selector close if focus lost option checkbox label."
+ }
+
+ , "optionsUserAgentWhitelistCategoryName": {
+ "message": "Brukeragent whitelist"
+ , "description": "Options page whitelist category title."
+ }
+ , "optionsUserAgentWhitelistCategoryDescription": {
+ "message": "Sider hvor man kan erstatte brukeragent med en Chrome-versjon for kompatibilitet. Må være et gjenkjennbart mønster."
+ , "description": "Options page whitelist category description."
+ }
+ , "optionsUserAgentWhitelistEnabled": {
+ "message": "Skru på whitelist"
+ , "description": "Whitelist enabled checkbox label."
+ }
+ , "optionsUserAgentWhitelistRestrictedEnabled": {
+ "message": "Skru på "
+ , "description": "Whitelist restricted mode enabled checkbox label."
+ }
+ , "optionsUserAgentWhitelistRestrictedEnabledDescription": {
+ "message": "Legg også til whitelist-begrensninger til side smo prøvde å laste cast-funksjonalitet uavhengig av nåværende brukeragent."
+ , "description": "Whitelist restricted mode enabled description."
+ }
+ , "optionsUserAgentWhitelistContent": {
+ "message": "Match mønster"
+ , "description": "Match patterns editor widget label."
+ }
+ , "optionsUserAgentWhitelistBasicView": {
+ "message": "Standard visning"
+ , "description": "Switch to basic view button title."
+ }
+ , "optionsUserAgentWhitelistRawView": {
+ "message": "Rå visning"
+ , "description": "Switch to raw view button title."
+ }
+ , "optionsUserAgentWhitelistSaveRaw": {
+ "message": "Lagre rå"
+ , "description": "Save raw view edits button title."
+ }
+ , "optionsUserAgentWhitelistAddItem": {
+ "message": "Legg til"
+ , "description": "Add new whitelist item button title."
+ }
+ , "optionsUserAgentWhitelistEditItem": {
+ "message": "Rediger"
+ , "description": "Edit whitelist item button title. Displayed on each item."
+ }
+ , "optionsUserAgentWhitelistRemoveItem": {
+ "message": "Fjern"
+ , "description": "Remove whitelist item button title. Displayed on each item."
+ }
+ , "optionsUserAgentWhitelistInvalidMatchPattern": {
+ "message": "Ugyldig mønster $matchPattern$"
+ , "description": "Error displayed by input indicating an invalid match pattern."
+ , "placeholders": {
+ "matchPattern": {
+ "content": "$1"
+ , "example": "http://example"
+ }
+ }
+ }
+
+ , "optionsMirroringCategoryName": {
+ "message": "Skjerm/fane-casting"
+ , "description": "Options page mirroring category name."
+ }
+ , "optionsMirroringCategoryDescription": {
+ "message": "Speiler til en Chromecast mottagerapp."
+ , "description": "Options page mirroring category description."
+ }
+ , "optionsMirroringEnabled": {
+ "message": "Skru på skjerm/fane-casting (eksperimentell)"
+ , "description": "Mirroring enabled checkbox label."
+ }
+ , "optionsMirroringAppId": {
+ "message": "Speilingsapp-ID"
+ , "description": "Mirroring app ID input label."
+ }
+ , "optionsMirroringAppIdDescription": {
+ "message": "App ID for en registrert Chromecast-mottager applikasjon. Kun for viderekommende. Må være kompatibel med standard-appen (se Github repo)"
+ , "description": "Mirroring app ID option description."
+ }
+
+ , "optionsOptionRecommended": {
+ "message": "anbefalt"
+ , "description": "Badge next to option label indicating boolean option is recommended enabled."
+ }
+
+ , "optionsReset": {
+ "message": "Tilbakestill verdier"
+ , "description": "Restore default options button label."
+ }
+ , "optionsSave": {
+ "message": "Lagre"
+ , "description": "Save options button label."
+ }
+ , "optionsSaved": {
+ "message": "Lagret"
+ , "description": "Status text displayed by save button once options have been successfully saved."
+ }
+}