You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
6.5 KiB
HTML
260 lines
6.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
|
|
|
<title>Indian Translate</title>
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js" charset="utf-8"></script>
|
|
<script src="./htmx.min.js"></script>
|
|
<style>
|
|
body {
|
|
background-color: #f4f4f4;
|
|
}
|
|
main {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-evenly;
|
|
gap: 2em 2em;
|
|
}
|
|
|
|
svg {
|
|
padding: 2em;
|
|
visibility: hidden;
|
|
opacity: 0;
|
|
transition: opacity 1s, visibility 2s;
|
|
}
|
|
|
|
svg.show {
|
|
visibility: visible;
|
|
opacity: 1;
|
|
}
|
|
|
|
h1 {
|
|
margin-block: 0.67em;
|
|
font-size: 2em;
|
|
}
|
|
|
|
.state {
|
|
stroke: black;
|
|
fill: none;
|
|
stroke-width: 0.5;
|
|
pointer-events: none;
|
|
}
|
|
.language {
|
|
stroke: red;
|
|
/* There has to be a fill, even if it's transparent, to allow
|
|
hover events to be recognized on the inside. */
|
|
/* fill: black;
|
|
fill-opacity: 0.0; */
|
|
fill-opacity: 0.8;
|
|
stroke-width: 1;
|
|
}
|
|
.translationText, .romanizationText {
|
|
visibility: hidden;
|
|
font-family: "Noto Sans";
|
|
/* font-size:1.2em; */
|
|
font-size: max(0.8vmax, 16px);
|
|
}
|
|
|
|
.romanizationText {
|
|
pointer-events: none;
|
|
}
|
|
|
|
.languageText {
|
|
pointer-events: none;
|
|
font-weight: bold;
|
|
/* font-size: 1em;*/
|
|
font-size: max(0.7vmax, 14px);
|
|
font-family: sans-serif;
|
|
visibility: hidden;
|
|
}
|
|
|
|
.district {
|
|
stroke: white;
|
|
stroke-width: 0.25;
|
|
transition: fill 0.3s;
|
|
fill: none;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.language:hover {
|
|
stroke-width: 2;
|
|
}
|
|
.districtText {
|
|
visibility: hidden;
|
|
}
|
|
/* .district:hover ~ .districtText {
|
|
visibility: visible;
|
|
}*/
|
|
|
|
|
|
.loading-indicator {
|
|
display: none;
|
|
}
|
|
.loading, .htmx-request.loading-indicator /* While request is being made */ {
|
|
display: inline;
|
|
}
|
|
|
|
/* Dim all other states */
|
|
/* Kinda wild that you can do this in plain CSS */
|
|
#indiaMap:has(.language:hover) .language:not(:hover) {
|
|
fill-opacity: 0.5;
|
|
transition: fill-opacity 0.3s;
|
|
}
|
|
|
|
#indiaMap .language:hover {
|
|
fill-opacity: 1;
|
|
transition: fill-opacity 0.3s;
|
|
}
|
|
|
|
section#textStuff {
|
|
min-width: 30em;
|
|
flex: 0 1 0;
|
|
}
|
|
|
|
section#textStuff ul {
|
|
font-size: 1.2em;
|
|
line-height: 1.5rem;
|
|
max-width: 35em;
|
|
}
|
|
|
|
section#textStuff li {
|
|
margin: 1em 0;
|
|
}
|
|
|
|
/* Position map load spinner in the middle of the SVG */
|
|
#svgContainer {
|
|
position: relative;
|
|
display: inline-block;
|
|
flex-shrink: 1;
|
|
flex-grow: 1;
|
|
max-width: 100%;
|
|
}
|
|
|
|
#svgContainer .mapLoadSpinner {
|
|
position: absolute;
|
|
top: 40%;
|
|
left: 40%;
|
|
}
|
|
|
|
/* Credit to https://lukehaas.me/projects/css-loaders/ */
|
|
.mapLoadSpinner,
|
|
.mapLoadSpinner:after {
|
|
border-radius: 50%;
|
|
width: 10em;
|
|
height: 10em;
|
|
transition: opacity 1s, visibility 2s;
|
|
}
|
|
.mapLoadSpinner.hide {
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
}
|
|
.mapLoadSpinner {
|
|
margin: 60px auto;
|
|
font-size: 10px;
|
|
position: relative;
|
|
text-indent: -9999em;
|
|
border-top: 1.1em solid rgba(255,158,83, 0.2);
|
|
border-right: 1.1em solid rgba(255,158,83, 0.2);
|
|
border-bottom: 1.1em solid rgba(255,158,83, 0.2);
|
|
border-left: 1.1em solid #ff9e53;
|
|
-webkit-transform: translateZ(0);
|
|
-ms-transform: translateZ(0);
|
|
transform: translateZ(0);
|
|
-webkit-animation: load8 1.1s infinite linear;
|
|
animation: load8 1.1s infinite linear;
|
|
}
|
|
@-webkit-keyframes load8 {
|
|
0% {
|
|
-webkit-transform: rotate(0deg);
|
|
transform: rotate(0deg);
|
|
}
|
|
100% {
|
|
-webkit-transform: rotate(360deg);
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
@keyframes load8 {
|
|
0% {
|
|
-webkit-transform: rotate(0deg);
|
|
transform: rotate(0deg);
|
|
}
|
|
100% {
|
|
-webkit-transform: rotate(360deg);
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
#fetchingText {
|
|
visibility: hidden;
|
|
}
|
|
@media only screen and (max-width: 1366px) {
|
|
main {
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
.district {
|
|
stroke-width: 0.1;
|
|
}
|
|
/* .translationText, .romanizationText {
|
|
font-size: 1em;
|
|
}
|
|
.languageText {
|
|
font-size: 0.8em;
|
|
} */
|
|
|
|
}
|
|
|
|
/* @media only screen and (max-width: 768px) {
|
|
.translationText, .romanizationText {
|
|
font-size: 0.8em;
|
|
}
|
|
.languageText {
|
|
font-size: 0.6em;
|
|
}
|
|
} */
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<main>
|
|
<section id="textStuff">
|
|
<h1>Indian Translate</h1>
|
|
<form hx-get="/submit" hx-swap=none hx-indicator="#loading-screen" hx-on::before-request="hideTranslationsAndShowText(event.detail.xhr.response)" hx-on::after-request="updateTranslations(event.detail.xhr.response)" class="translateForm" method="get">
|
|
<label for="query">Enter text to translate:</label>
|
|
<input type="text" name="query" id="query" required/>
|
|
<input type="submit" value="Translate"/>
|
|
</form>
|
|
<progress id="loading-screen" class="loading-indicator"></progress>
|
|
<h3 id="fetchingText">Fetching translations...</h3>
|
|
<noscript>
|
|
<h2>This website requires javascript to work.</h2>
|
|
</noscript>
|
|
<ul>
|
|
<li>Enter text in English. Translations are displayed on the map, along with romanizations (translation converted to Latin script).</li>
|
|
<li>Hover over a language region (denoted by color) to see the language spoken in the region. Language boundaries were drawn using census data; they may be inaccurate.</li>
|
|
<li>Translations are retrieved from Google Translate - they may be innacurate.</li>
|
|
<li>Romanizations are made with the <kbd>ai4bharat-transliteration</kbd> AI model, developed by <a href="https://ai4bharat.iitm.ac.in/">Ai4Bharat</a>.</li>
|
|
|
|
</ul>
|
|
|
|
</section>
|
|
|
|
<section id="svgContainer">
|
|
<div id="mapLoadSpinner" class="mapLoadSpinner"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<script type="text/javascript" src="index.js"></script>
|
|
<script type="text/javascript" src="updateTranslations.js"></script>
|
|
<script type="text/javascript" src="svgHoverListener.js"></script>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|