{"id":49177,"date":"2026-08-31T16:03:37","date_gmt":"2026-08-31T20:03:37","guid":{"rendered":"https:\/\/detroitmarthoma.org\/home\/?page_id=49177"},"modified":"2026-08-31T16:03:42","modified_gmt":"2026-08-31T20:03:42","slug":"live-translation","status":"publish","type":"page","link":"https:\/\/detroitmarthoma.org\/home\/live-translation\/","title":{"rendered":"Live Translation"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"49177\" class=\"elementor elementor-49177\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-132848b e-flex e-con-boxed e-con e-parent\" data-id=\"132848b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-efce8a9 elementor-widget elementor-widget-shortcode\" data-id=\"efce8a9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">\r\n    <div id=\"dmtc-live-translation\">\r\n\r\n        <div class=\"dmtc-live-header\">\r\n\r\n            <div>\r\n\r\n                <div class=\"dmtc-live-status\">\r\n                    <span id=\"dmtc-live-dot\"><\/span>\r\n                    <span id=\"dmtc-status-text\">\r\n                        Connecting...\r\n                    <\/span>\r\n                <\/div>\r\n\r\n                <h2>\r\n                    Live Sermon Translation\r\n                <\/h2>\r\n\r\n                <div class=\"dmtc-language\">\r\n                    Malayalam \u2192 English\r\n                <\/div>\r\n\r\n            <\/div>\r\n\r\n            <div class=\"dmtc-font-controls\">\r\n\r\n                <button\r\n                    type=\"button\"\r\n                    id=\"dmtc-font-smaller\"\r\n                    aria-label=\"Decrease text size\">\r\n                    A\u2212\r\n                <\/button>\r\n\r\n                <button\r\n                    type=\"button\"\r\n                    id=\"dmtc-font-larger\"\r\n                    aria-label=\"Increase text size\">\r\n                    A+\r\n                <\/button>\r\n\r\n            <\/div>\r\n\r\n        <\/div>\r\n\r\n\r\n        <div\r\n            id=\"dmtc-sermon-container\"\r\n            aria-live=\"polite\">\r\n\r\n            <div id=\"dmtc-loading\">\r\n                Waiting for live translation...\r\n            <\/div>\r\n\r\n        <\/div>\r\n\r\n\r\n        <div class=\"dmtc-disclaimer\">\r\n\r\n            Live translation is generated automatically\r\n            and may contain transcription or translation errors.\r\n\r\n        <\/div>\r\n\r\n    <\/div>\r\n\r\n\r\n    <style>\r\n\r\n    #dmtc-live-translation {\r\n\r\n        max-width: 900px;\r\n        margin: 20px auto;\r\n        font-family: inherit;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-live-header {\r\n\r\n        display: flex;\r\n        justify-content: space-between;\r\n        align-items: center;\r\n        gap: 20px;\r\n\r\n        padding-bottom: 18px;\r\n\r\n        border-bottom: 1px solid #ddd;\r\n\r\n        margin-bottom: 25px;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-live-header h2 {\r\n\r\n        margin: 5px 0;\r\n        font-size: 30px;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-live-status {\r\n\r\n        display: flex;\r\n        align-items: center;\r\n        gap: 8px;\r\n\r\n        font-size: 14px;\r\n        font-weight: 600;\r\n\r\n    }\r\n\r\n\r\n    #dmtc-live-dot {\r\n\r\n        width: 10px;\r\n        height: 10px;\r\n\r\n        border-radius: 50%;\r\n\r\n        background: #999;\r\n\r\n        display: inline-block;\r\n\r\n    }\r\n\r\n\r\n    #dmtc-live-dot.live {\r\n\r\n        background: #d00000;\r\n\r\n        animation: dmtcPulse 2s infinite;\r\n\r\n    }\r\n\r\n\r\n    @keyframes dmtcPulse {\r\n\r\n        0% {\r\n            opacity: 1;\r\n        }\r\n\r\n        50% {\r\n            opacity: .4;\r\n        }\r\n\r\n        100% {\r\n            opacity: 1;\r\n        }\r\n\r\n    }\r\n\r\n\r\n    .dmtc-language {\r\n\r\n        font-size: 14px;\r\n        opacity: .7;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-font-controls {\r\n\r\n        display: flex;\r\n        gap: 8px;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-font-controls button {\r\n\r\n        min-width: 50px;\r\n        min-height: 45px;\r\n\r\n        border: 1px solid #ccc;\r\n        border-radius: 8px;\r\n\r\n        background: white;\r\n\r\n        cursor: pointer;\r\n\r\n        font-size: 18px;\r\n        font-weight: 600;\r\n\r\n    }\r\n\r\n\r\n    #dmtc-sermon-container {\r\n\r\n        font-size: 22px;\r\n        line-height: 1.7;\r\n\r\n        transition: font-size .2s;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-sermon-entry {\r\n\r\n        padding: 14px 0;\r\n\r\n        border-bottom: 1px solid #eee;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-sermon-time {\r\n\r\n        font-size: 12px;\r\n        opacity: .5;\r\n\r\n        margin-bottom: 4px;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-sermon-text {\r\n\r\n        margin: 0;\r\n\r\n    }\r\n\r\n\r\n    #dmtc-loading {\r\n\r\n        padding: 30px 0;\r\n\r\n        text-align: center;\r\n\r\n        opacity: .6;\r\n\r\n    }\r\n\r\n\r\n    .dmtc-disclaimer {\r\n\r\n        margin-top: 30px;\r\n\r\n        padding: 15px;\r\n\r\n        border-top: 1px solid #ddd;\r\n\r\n        font-size: 13px;\r\n\r\n        text-align: center;\r\n\r\n        opacity: .6;\r\n\r\n    }\r\n\r\n\r\n    @media(max-width: 600px) {\r\n\r\n        .dmtc-live-header {\r\n\r\n            align-items: flex-start;\r\n\r\n        }\r\n\r\n\r\n        .dmtc-live-header h2 {\r\n\r\n            font-size: 24px;\r\n\r\n        }\r\n\r\n\r\n        #dmtc-sermon-container {\r\n\r\n            font-size: 20px;\r\n\r\n        }\r\n\r\n    }\r\n\r\n    <\/style>\r\n\r\n\r\n    <script>\r\n\r\n    document.addEventListener(\r\n        \"DOMContentLoaded\",\r\n        function () {\r\n\r\n            const container =\r\n                document.getElementById(\r\n                    \"dmtc-sermon-container\"\r\n                );\r\n\r\n            const statusText =\r\n                document.getElementById(\r\n                    \"dmtc-status-text\"\r\n                );\r\n\r\n            const liveDot =\r\n                document.getElementById(\r\n                    \"dmtc-live-dot\"\r\n                );\r\n\r\n            const larger =\r\n                document.getElementById(\r\n                    \"dmtc-font-larger\"\r\n                );\r\n\r\n            const smaller =\r\n                document.getElementById(\r\n                    \"dmtc-font-smaller\"\r\n                );\r\n\r\n\r\n            let fontSize = 22;\r\n\r\n            let lastPayload = \"\";\r\n\r\n\r\n            async function loadTranslation() {\r\n\r\n                try {\r\n\r\n                    const response =\r\n                        await fetch(\r\n                            \"\/home\/wp-json\/dmtc\/v1\/live-sermon?time=\"\r\n                            + Date.now(),\r\n                            {\r\n                                cache: \"no-store\"\r\n                            }\r\n                        );\r\n\r\n\r\n                    if (!response.ok) {\r\n\r\n                        throw new Error(\r\n                            \"Unable to retrieve translation.\"\r\n                        );\r\n\r\n                    }\r\n\r\n\r\n                    const data =\r\n                        await response.json();\r\n\r\n\r\n                    const newPayload =\r\n                        JSON.stringify(data);\r\n\r\n\r\n                    if (newPayload === lastPayload) {\r\n                        return;\r\n                    }\r\n\r\n\r\n                    lastPayload = newPayload;\r\n\r\n\r\n                    if (\r\n                        data.status === \"live\"\r\n                        &&\r\n                        data.translations\r\n                        &&\r\n                        data.translations.length\r\n                    ) {\r\n\r\n                        statusText.textContent =\r\n                            \"LIVE \u2014 Sunday Worship\";\r\n\r\n                        liveDot.classList.add(\r\n                            \"live\"\r\n                        );\r\n\r\n\r\n                        container.innerHTML = \"\";\r\n\r\n\r\n                        data.translations\r\n                            .forEach(function (entry) {\r\n\r\n                                const block =\r\n                                    document.createElement(\r\n                                        \"div\"\r\n                                    );\r\n\r\n                                block.className =\r\n                                    \"dmtc-sermon-entry\";\r\n\r\n\r\n                                const time =\r\n                                    document.createElement(\r\n                                        \"div\"\r\n                                    );\r\n\r\n                                time.className =\r\n                                    \"dmtc-sermon-time\";\r\n\r\n                                time.textContent =\r\n                                    entry.time;\r\n\r\n\r\n                                const text =\r\n                                    document.createElement(\r\n                                        \"p\"\r\n                                    );\r\n\r\n                                text.className =\r\n                                    \"dmtc-sermon-text\";\r\n\r\n                                text.textContent =\r\n                                    entry.text;\r\n\r\n\r\n                                block.appendChild(time);\r\n                                block.appendChild(text);\r\n\r\n                                container.appendChild(\r\n                                    block\r\n                                );\r\n\r\n                            });\r\n\r\n\r\n                        \/\/ Automatically stay near newest translation\r\n                        const entries =\r\n                            container.querySelectorAll(\r\n                                \".dmtc-sermon-entry\"\r\n                            );\r\n\r\n                        if (entries.length) {\r\n\r\n                            entries[\r\n                                entries.length - 1\r\n                            ].scrollIntoView({\r\n                                behavior: \"smooth\",\r\n                                block: \"nearest\"\r\n                            });\r\n\r\n                        }\r\n\r\n                    }\r\n\r\n                    else {\r\n\r\n                        statusText.textContent =\r\n                            \"Translation Offline\";\r\n\r\n                        liveDot.classList.remove(\r\n                            \"live\"\r\n                        );\r\n\r\n                        container.innerHTML =\r\n                            \"<div id='dmtc-loading'>\"\r\n                            +\r\n                            \"Live translation is not currently active.\"\r\n                            +\r\n                            \"<\/div>\";\r\n\r\n                    }\r\n\r\n                }\r\n\r\n                catch (error) {\r\n\r\n                    statusText.textContent =\r\n                        \"Connection interrupted\";\r\n\r\n                    liveDot.classList.remove(\r\n                        \"live\"\r\n                    );\r\n\r\n                }\r\n\r\n            }\r\n\r\n\r\n            larger.addEventListener(\r\n                \"click\",\r\n                function () {\r\n\r\n                    fontSize =\r\n                        Math.min(\r\n                            fontSize + 2,\r\n                            36\r\n                        );\r\n\r\n                    container.style.fontSize =\r\n                        fontSize + \"px\";\r\n\r\n                }\r\n            );\r\n\r\n\r\n            smaller.addEventListener(\r\n                \"click\",\r\n                function () {\r\n\r\n                    fontSize =\r\n                        Math.max(\r\n                            fontSize - 2,\r\n                            16\r\n                        );\r\n\r\n                    container.style.fontSize =\r\n                        fontSize + \"px\";\r\n\r\n                }\r\n            );\r\n\r\n\r\n            loadTranslation();\r\n\r\n            setInterval(\r\n                loadTranslation,\r\n                2000\r\n            );\r\n\r\n        }\r\n    );\r\n\r\n    <\/script>\r\n\r\n    <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-49177","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/pages\/49177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/comments?post=49177"}],"version-history":[{"count":4,"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/pages\/49177\/revisions"}],"predecessor-version":[{"id":49181,"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/pages\/49177\/revisions\/49181"}],"wp:attachment":[{"href":"https:\/\/detroitmarthoma.org\/home\/wp-json\/wp\/v2\/media?parent=49177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}