diff --git a/dashboard-ui/bower_components/emby-apiclient/.bower.json b/dashboard-ui/bower_components/emby-apiclient/.bower.json index 26810f2e02..ead1da15dc 100644 --- a/dashboard-ui/bower_components/emby-apiclient/.bower.json +++ b/dashboard-ui/bower_components/emby-apiclient/.bower.json @@ -16,12 +16,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.1.62", - "_release": "1.1.62", + "version": "1.1.63", + "_release": "1.1.63", "_resolution": { "type": "version", - "tag": "1.1.62", - "commit": "da75c70974125e7666f6e01738850b010f6276b6" + "tag": "1.1.63", + "commit": "076ec0b311164c5a85aeae3375af2c23be9b20fb" }, "_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git", "_target": "^1.1.51", diff --git a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js index aad6c10b67..71845c59bf 100644 --- a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js +++ b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js @@ -215,7 +215,7 @@ return connectUser; }; - var minServerVersion = '3.0.5870'; + var minServerVersion = '3.0.5882'; self.minServerVersion = function (val) { if (val) { @@ -309,7 +309,6 @@ existingServer.DateLastAccessed = new Date().getTime(); existingServer.LastConnectionMode = ConnectionMode.Manual; existingServer.ManualAddress = apiClient.serverAddress(); - existingServer.PreferredConnectionMode = ConnectionMode.Manual; apiClient.serverInfo(existingServer); apiClient.onAuthenticated = function (instance, result) { @@ -998,9 +997,6 @@ if (server.LastConnectionMode != null) { //tests.push(server.LastConnectionMode); } - if (server.PreferredConnectionMode != null) { - tests.push(server.PreferredConnectionMode); - } if (tests.indexOf(ConnectionMode.Manual) == -1) { tests.push(ConnectionMode.Manual); } if (tests.indexOf(ConnectionMode.Local) == -1) { tests.push(ConnectionMode.Local); } if (tests.indexOf(ConnectionMode.Remote) == -1) { tests.push(ConnectionMode.Remote); } @@ -1062,13 +1058,17 @@ enableRetry = true; timeout = 8000; + + if (stringEqualsIgnoreCase(address, server.ManualAddress)) { + skipTest = true; + } } else if (mode == ConnectionMode.Manual) { - if (stringEqualsIgnoreCase(address, server.LocalAddress) || - stringEqualsIgnoreCase(address, server.RemoteAddress)) { - skipTest = true; + if (stringEqualsIgnoreCase(address, server.LocalAddress)) { + enableRetry = true; + timeout = 8000; } } diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json index 971a5d549c..24dfc6c309 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json @@ -15,12 +15,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.4.33", - "_release": "1.4.33", + "version": "1.4.34", + "_release": "1.4.34", "_resolution": { "type": "version", - "tag": "1.4.33", - "commit": "e78684c1db2e30856c4a16ac24a49d4aae625e56" + "tag": "1.4.34", + "commit": "412b8b2523dd3d55952f1caeb0c2cb97b51d3781" }, "_source": "https://github.com/MediaBrowser/emby-webcomponents.git", "_target": "^1.2.0", diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js index 5cb4b47b1e..c6d58936f2 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js +++ b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js @@ -1,4 +1,4 @@ -define(['require', 'browser', 'globalize', 'connectionManager', 'loading', 'scrollHelper', 'datetime', 'focusManager', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'clearButtonStyle', 'css!./guide.css', 'html!./../icons/mediainfo.html', 'html!./../icons/nav.html', 'scrollStyles', 'emby-button'], function (require, browser, globalize, connectionManager, loading, scrollHelper, datetime, focusManager, imageLoader, events, layoutManager, itemShortcuts, registrationServices) { +define(['require', 'browser', 'globalize', 'connectionManager', 'serverNotifications', 'loading', 'scrollHelper', 'datetime', 'focusManager', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'clearButtonStyle', 'css!./guide.css', 'html!./../icons/mediainfo.html', 'html!./../icons/nav.html', 'scrollStyles', 'emby-button'], function (require, browser, globalize, connectionManager, serverNotifications, loading, scrollHelper, datetime, focusManager, imageLoader, events, layoutManager, itemShortcuts, registrationServices) { function Guide(options) { @@ -11,6 +11,12 @@ }; self.destroy = function () { + + events.off(serverNotifications, 'TimerCreated', onTimerCreated); + events.off(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated); + events.off(serverNotifications, 'TimerCancelled', onTimerCancelled); + events.off(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled); + clearCurrentTimeUpdateInterval(); itemShortcuts.off(options.element); items = {}; @@ -736,6 +742,59 @@ target.addEventListener(type, handler, optionsOrCapture); } + function onTimerCreated(e, apiClient, data) { + + var programId = data.ProgramId; + // This could be null, not supported by all tv providers + var newTimerId = data.Id; + + // find guide cells by program id, ensure timer icon + var cells = options.element.querySelectorAll('.programCell[data-id="' + programId + '"]'); + for (var i = 0, length = cells.length; i < length; i++) { + var cell = cells[i]; + + var icon = cell.querySelector('.timerIcon'); + if (!icon) { + cell.insertAdjacentHTML('beforeend', ''); + } + + if (newTimerId) { + cell.setAttribute('data-timerid', newTimerId); + } + } + } + + function onSeriesTimerCreated(e, apiClient, data) { + } + + function onTimerCancelled(e, apiClient, data) { + var id = data.Id; + // find guide cells by timer id, remove timer icon + var cells = options.element.querySelectorAll('.programCell[data-timerid="' + id + '"]'); + for (var i = 0, length = cells.length; i < length; i++) { + var cells = cells[i]; + var icon = cell.querySelector('.timerIcon'); + if (icon) { + icon.parentNode.removeChild(icon); + } + cell.removeAttribute('data-timerid'); + } + } + + function onSeriesTimerCancelled(e, apiClient, data) { + var id = data.Id; + // find guide cells by timer id, remove timer icon + var cells = options.element.querySelectorAll('.programCell[data-seriestimerid="' + id + '"]'); + for (var i = 0, length = cells.length; i < length; i++) { + var cells = cells[i]; + var icon = cell.querySelector('.seriesTimerIcon'); + if (icon) { + icon.parentNode.removeChild(icon); + } + cell.removeAttribute('data-seriestimerid'); + } + } + require(['text!./tvguide.template.html'], function (template) { var context = options.element; context.innerHTML = globalize.translateDocument(template, 'core'); @@ -772,6 +831,11 @@ events.trigger(self, 'load'); + events.on(serverNotifications, 'TimerCreated', onTimerCreated); + events.on(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated); + events.on(serverNotifications, 'TimerCancelled', onTimerCancelled); + events.on(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled); + self.refresh(); }); }; diff --git a/dashboard-ui/bower_components/emby-webcomponents/servernotifications.js b/dashboard-ui/bower_components/emby-webcomponents/servernotifications.js index 7387708a73..d150a21fac 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/servernotifications.js +++ b/dashboard-ui/bower_components/emby-webcomponents/servernotifications.js @@ -26,6 +26,10 @@ define(['connectionManager', 'events'], function (connectionManager, events) { } } } + else if (msg.MessageType === "TimerCreated" || msg.MessageType === "SeriesTimerCreated" || msg.MessageType === "TimerCancelled" || msg.MessageType === "SeriesTimerCancelled") { + + events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]); + } } function bindEvents(apiClient) { diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/da.json b/dashboard-ui/bower_components/emby-webcomponents/strings/da.json index d6abbd58ac..50cda4394d 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/da.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/da.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "Confirm Deletion", "MySubtitles": "My Subtitles", "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/de.json b/dashboard-ui/bower_components/emby-webcomponents/strings/de.json index 8e130c838c..701db5b1fd 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/de.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/de.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "Confirm Deletion", "MySubtitles": "My Subtitles", "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/es-MX.json b/dashboard-ui/bower_components/emby-webcomponents/strings/es-MX.json index fb3f41f261..93c0ac131c 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/es-MX.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/es-MX.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "Confirm Deletion", "MySubtitles": "My Subtitles", "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/kk.json b/dashboard-ui/bower_components/emby-webcomponents/strings/kk.json index 08c2d402b7..b19334a052 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/kk.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/kk.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "\u0416\u043e\u044e\u0434\u044b \u0440\u0430\u0441\u0442\u0430\u0443", "MySubtitles": "\u041c\u0435\u043d\u0456\u04a3 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0456\u043c", "MessageDownloadQueued": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u043a\u0435\u0437\u0435\u043a\u0442\u0435.", - "EditSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u04e9\u04a3\u0434\u0435\u0443" + "EditSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u04e9\u04a3\u0434\u0435\u0443", + "UnlockGuide": "\u0422\u0435\u043b\u0435\u0433\u0438\u0434\u0442\u0456 \u049b\u04b1\u0440\u0441\u0430\u0443\u0434\u0430\u043d \u0431\u043e\u0441\u0430\u0442\u0443" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/nb.json b/dashboard-ui/bower_components/emby-webcomponents/strings/nb.json index 385100dd9c..4e77d1a4d5 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/nb.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/nb.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "Confirm Deletion", "MySubtitles": "My Subtitles", "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/nl.json b/dashboard-ui/bower_components/emby-webcomponents/strings/nl.json index ba06032d26..44c2e4b63b 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/nl.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/nl.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "Confirm Deletion", "MySubtitles": "My Subtitles", "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/pt-BR.json b/dashboard-ui/bower_components/emby-webcomponents/strings/pt-BR.json index b710dcc315..80ef9ac833 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/pt-BR.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/pt-BR.json @@ -8,7 +8,7 @@ "AttributeLive": "Ao Vivo", "TrackCount": "{0} faixas", "ItemCount": "{0} itens", - "ValueSeriesYearToPresent": "{0}-Present", + "ValueSeriesYearToPresent": "{0}-Presente", "ReleaseYearValue": "Ano de lan\u00e7amento: {0}", "OriginalAirDateValue": "Data de exibi\u00e7\u00e3o original: {0}", "EndsAtValue": "Termina \u00e0s {0}", @@ -69,15 +69,16 @@ "OptionNew": "Novo...", "LabelPlaylist": "Lista de Reprodu\u00e7\u00e3o:", "AddToPlaylist": "Adicionar \u00e0 lista de reprodu\u00e7\u00e3o", - "Subtitles": "Subtitles", - "SearchForSubtitles": "Search for Subtitles", - "LabelLanguage": "Language:", - "Search": "Search", - "NoSubtitleSearchResultsFound": "No results found.", - "File": "File", - "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", - "ConfirmDeletion": "Confirm Deletion", - "MySubtitles": "My Subtitles", - "MessageDownloadQueued": "Download queued.", - "EditSubtitles": "Edit Subtitles" + "Subtitles": "Legendas", + "SearchForSubtitles": "Buscar Legendas", + "LabelLanguage": "Idioma:", + "Search": "Busca", + "NoSubtitleSearchResultsFound": "Nenhum resultado encontrado.", + "File": "Arquivo", + "MessageAreYouSureDeleteSubtitles": "Deseja realmente excluir este arquivo de legendas?", + "ConfirmDeletion": "Confirmar Exclus\u00e3o", + "MySubtitles": "Minhas Legendas", + "MessageDownloadQueued": "Download enfileirado.", + "EditSubtitles": "Editar Legendas", + "UnlockGuide": "Unlock Guide" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/pt-PT.json b/dashboard-ui/bower_components/emby-webcomponents/strings/pt-PT.json new file mode 100644 index 0000000000..250c221f83 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/pt-PT.json @@ -0,0 +1,84 @@ +{ + "ValueSpecialEpisodeName": "Especial - {0}", + "Share": "Partilhar", + "ServerUpdateNeeded": "Este Servidor Emby precisa ser atualizado. Para fazer download da vers\u00e3o mais recente, por favor visite {0}", + "LiveTvGuideRequiresUnlock": "The Live TV Guide is currently limited to {0} channels. Click the unlock button to learn how to enjoy the full experience.", + "AttributeNew": "Novo", + "AttributePremiere": "Estreia", + "AttributeLive": "Ao vivo", + "TrackCount": "{0} faixas", + "ItemCount": "{0} itens", + "ValueSeriesYearToPresent": "{0}-Presente", + "ReleaseYearValue": "Ano de lan\u00e7amento: {0}", + "OriginalAirDateValue": "Original air date: {0}", + "EndsAtValue": "Ends at {0}", + "OptionSundayShort": "Sun", + "OptionMondayShort": "Mon", + "OptionTuesdayShort": "Tue", + "OptionWednesdayShort": "Wed", + "OptionThursdayShort": "Thu", + "OptionFridayShort": "Fri", + "OptionSaturdayShort": "Sat", + "HeaderSelectDate": "Select Date", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "ButtonGotIt": "Got It", + "RecordingCancelled": "Recording cancelled.", + "RecordingScheduled": "Recording scheduled.", + "SeriesRecordingScheduled": "Series recording scheduled.", + "HeaderNewRecording": "New Recording", + "Sunday": "Sunday", + "Monday": "Monday", + "Tuesday": "Tuesday", + "Wednesday": "Wednesday", + "Thursday": "Thursday", + "Friday": "Friday", + "Saturday": "Saturday", + "Days": "Days", + "RecordSeries": "Record series", + "LabelPrePaddingMinutes": "Pre-padding minutes:", + "LabelPostPaddingMinutes": "Post-padding minutes:", + "RecordOnAllChannels": "Record on all channels", + "RecordAnytime": "Record at any time", + "RecordOnlyNewEpisodes": "Record only new episodes", + "HeaderBecomeProjectSupporter": "Get Emby Premiere", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "MessageActiveSubscriptionRequiredSeriesRecordings": "An active Emby Premiere subscription is required in order to create automated series recordings.", + "OptionConvertRecordingsToStreamingFormat": "Automatically convert recordings to a streaming friendly format", + "OptionConvertRecordingsToStreamingFormatHelp": "Recordings will be converted on the fly to MP4 for easy playback on your devices.", + "FeatureRequiresEmbyPremiere": "This feature requires an active Emby Premiere subscription.", + "Record": "Record", + "Save": "Save", + "Edit": "Edit", + "Download": "Download", + "Advanced": "Advanced", + "Delete": "Delete", + "HeaderDeleteItem": "Delete Item", + "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", + "Refresh": "Refresh", + "RefreshQueued": "Refresh queued.", + "AddToCollection": "Add to Collection", + "NewCollection": "New Collection", + "LabelCollection": "Collection:", + "Help": "Help", + "NewCollectionHelp": "Collections allow you to create personalized groupings of movies and other library content.", + "SearchForCollectionInternetMetadata": "Search the internet for artwork and metadata", + "LabelName": "Name:", + "NewCollectionNameExample": "Example: Star Wars Collection", + "MessageItemsAdded": "Items added.", + "OptionNew": "New...", + "LabelPlaylist": "Playlist:", + "AddToPlaylist": "Add to Playlist", + "Subtitles": "Subtitles", + "SearchForSubtitles": "Search for Subtitles", + "LabelLanguage": "Language:", + "Search": "Search", + "NoSubtitleSearchResultsFound": "No results found.", + "File": "File", + "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", + "ConfirmDeletion": "Confirm Deletion", + "MySubtitles": "My Subtitles", + "MessageDownloadQueued": "Download queued.", + "EditSubtitles": "Edit Subtitles", + "UnlockGuide": "Unlock Guide" +} \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/strings/ru.json b/dashboard-ui/bower_components/emby-webcomponents/strings/ru.json index 995169a51d..437f79d532 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/strings/ru.json +++ b/dashboard-ui/bower_components/emby-webcomponents/strings/ru.json @@ -79,5 +79,6 @@ "ConfirmDeletion": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f", "MySubtitles": "\u041c\u043e\u0438 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b", "MessageDownloadQueued": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438.", - "EditSubtitles": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b" + "EditSubtitles": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b", + "UnlockGuide": "\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043b\u0435\u0433\u0438\u0434" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/polymer/.bower.json b/dashboard-ui/bower_components/polymer/.bower.json index e3120e6882..4782b3c50f 100644 --- a/dashboard-ui/bower_components/polymer/.bower.json +++ b/dashboard-ui/bower_components/polymer/.bower.json @@ -39,6 +39,6 @@ "commit": "ce5b9fb2d8aa03c698410e2e55cffcfa0b788a3a" }, "_source": "git://github.com/Polymer/polymer.git", - "_target": "^1.1.0", + "_target": "^1.0.0", "_originalSource": "Polymer/polymer" } \ No newline at end of file diff --git a/dashboard-ui/scripts/librarydisplay.js b/dashboard-ui/scripts/librarydisplay.js index fb3b01ff84..d6e794e34f 100644 --- a/dashboard-ui/scripts/librarydisplay.js +++ b/dashboard-ui/scripts/librarydisplay.js @@ -33,8 +33,8 @@ ApiClient.getServerConfiguration().then(function (config) { config.EnableFolderView = form.querySelector('.chkFolderView').checked; - config.EnableGroupingIntoCollections = form.querySelector('.chkDisplaySpecialsWithinSeasons').checked; - config.DisplaySpecialsWithinSeasons = form.querySelector('.chkGroupMoviesIntoCollections').checked; + config.EnableGroupingIntoCollections = form.querySelector('.chkGroupMoviesIntoCollections').checked; + config.DisplaySpecialsWithinSeasons = form.querySelector('.chkDisplaySpecialsWithinSeasons').checked; ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult); }); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 34c7d097ef..e81a251451 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -2280,7 +2280,7 @@ var AppInfo = {}; var baseUrl = 'bower_components/emby-webcomponents/strings/'; - var languages = ['da', 'de', 'en-US', 'es-MX', 'kk', 'nb', 'nl', 'pt-BR', 'ru']; + var languages = ['da', 'de', 'en-US', 'es-MX', 'kk', 'nb', 'nl', 'pt-BR', 'pt-PT', 'ru']; var translations = languages.map(function (i) { return {