Compare commits

...

15 Commits

Author SHA1 Message Date
8f7d4e477f Added my name to the bottom 2025-06-29 17:34:24 -05:00
945d3d6526 Paying my dues 2025-05-28 08:53:57 -04:00
485a3efd8f Added HTML sanitization for translate server 2025-04-19 10:43:42 -04:00
17878106d4 Added maximum length to input text 2025-04-18 22:03:49 -05:00
67fc0d4297 Added changes from production use 2025-04-18 22:02:07 -05:00
6716a4cd40 Updated styling for buttons and textbox; made some flexbox changes 2025-04-18 22:01:50 -05:00
4e4570ed03 Font resizing stuff; looks better on desktop and mobile now 2025-04-16 16:03:38 -05:00
12d53370fb Updated translations DB 2025-04-15 15:40:24 -05:00
11b9635e50 Added responsive font resizing (with viewport width); removed dangling 'p' tag 2025-04-15 15:40:11 -05:00
d769797136 Added horizontal alignment for each language text; moved Hindi text down 2025-04-15 15:38:59 -05:00
4804497b3c Updated positioning of text 2025-04-15 09:49:16 -05:00
80529e5882 Updated translations DB from production use 2025-04-15 08:58:44 -05:00
f6abc396b6 Added intermediate responsive font sizes 2025-04-15 09:50:31 -04:00
094d756a07 Updated flexbox styling 2025-04-14 16:54:44 -04:00
fca0d3a5fa Added help text 2025-04-12 19:28:41 -04:00
6 changed files with 187 additions and 47 deletions

View File

@@ -9,14 +9,17 @@ require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/longrunning v0.6.2 // indirect cloud.google.com/go/longrunning v0.6.2 // indirect
cloud.google.com/go/translate v1.12.3 // indirect cloud.google.com/go/translate v1.12.3 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/s2a-go v0.1.8 // indirect github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/googleapis/gax-go/v2 v2.14.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel v1.29.0 // indirect

View File

@@ -11,6 +11,8 @@ cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3
cloud.google.com/go/translate v1.12.3 h1:XJ7LipYJi80BCgVk2lx1fwc7DIYM6oV2qx1G4IAGQ5w= cloud.google.com/go/translate v1.12.3 h1:XJ7LipYJi80BCgVk2lx1fwc7DIYM6oV2qx1G4IAGQ5w=
cloud.google.com/go/translate v1.12.3/go.mod h1:qINOVpgmgBnY4YTFHdfVO4nLrSBlpvlIyosqpGEgyEg= cloud.google.com/go/translate v1.12.3/go.mod h1:qINOVpgmgBnY4YTFHdfVO4nLrSBlpvlIyosqpGEgyEg=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -25,12 +27,16 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gT
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o=
github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=

View File

@@ -16,6 +16,8 @@ import (
translate "cloud.google.com/go/translate/apiv3" translate "cloud.google.com/go/translate/apiv3"
"cloud.google.com/go/translate/apiv3/translatepb" "cloud.google.com/go/translate/apiv3/translatepb"
"github.com/microcosm-cc/bluemonday"
) )
const project_id string = "india-translate-testing-452100" const project_id string = "india-translate-testing-452100"
@@ -72,6 +74,7 @@ var lang_codes []string = []string{
} }
var db *sqlx.DB var db *sqlx.DB
var p *bluemonday.Policy
func cleanup() { func cleanup() {
db.Close() db.Close()
@@ -149,6 +152,7 @@ func translateTextHelper(projectID string, sourceLang string, targetLang string,
func handler(w http.ResponseWriter, r *http.Request) { func handler(w http.ResponseWriter, r *http.Request) {
queries := r.URL.Query() queries := r.URL.Query()
toTranslate := queries["query"][0] toTranslate := queries["query"][0]
toTranslate = p.Sanitize(toTranslate)
if ok, translation := getCachedTranslation(toTranslate); ok { if ok, translation := getCachedTranslation(toTranslate); ok {
translationJson, _ := json.Marshal(translation) translationJson, _ := json.Marshal(translation)
@@ -182,6 +186,10 @@ func main() {
panic(err) panic(err)
} }
defer db.Close() defer db.Close()
// HTML sanitization
p = bluemonday.UGCPolicy()
// Catch signal // Catch signal
sigs := make(chan os.Signal, 1) sigs := make(chan os.Signal, 1)
signal.Notify(sigs) signal.Notify(sigs)

View File

@@ -57,7 +57,9 @@
.translationText, .romanizationText { .translationText, .romanizationText {
visibility: hidden; visibility: hidden;
font-family: "Noto Sans"; font-family: "Noto Sans";
font-size:1.2em; /* font-size:1.2em; */
/* font-size: max(0.8vmax, 16px);*/
font-size: 1.2em;
} }
.romanizationText { .romanizationText {
@@ -67,7 +69,8 @@
.languageText { .languageText {
pointer-events: none; pointer-events: none;
font-weight: bold; font-weight: bold;
font-size: 1em; /* font-size: 1em;*/
font-size: max(0.7vmax, 14px);
font-family: sans-serif; font-family: sans-serif;
visibility: hidden; visibility: hidden;
} }
@@ -110,10 +113,83 @@
transition: fill-opacity 0.3s; transition: fill-opacity 0.3s;
} }
section#textStuff {
min-width: 30em;
/* flex: 0 1 0; */
flex: 0 0 auto;
}
section#textStuff ul {
font-size: 1.2em;
line-height: 1.5rem;
max-width: 35em;
}
section#textStuff li {
margin: 1em 0;
}
#query {
font-size: 1em;
padding: 6px 8px;
margin-right: 1em;
}
#submitButton {
appearance: none;
background-color: #2ea44f;
border: 1px solid rgba(27, 31, 35, .15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 1em;
font-weight: 600;
line-height: 1.2em;
padding: 6px 16px;
position: relative;
text-align: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
}
#submitButton:focus:not(:focus-visible):not(.focus-visible) {
box-shadow: none;
outline: none;
}
#submitButton:hover {
background-color: #2c974b;
}
#submitButton:focus {
box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
outline: none;
}
#submitButton:disabled {
background-color: #94d3a2;
border-color: rgba(27, 31, 35, .1);
color: rgba(255, 255, 255, .8);
cursor: default;
}
#submitButton:active {
background-color: #298e46;
box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
}
/* Position map load spinner in the middle of the SVG */ /* Position map load spinner in the middle of the SVG */
#svgContainer { #svgContainer {
position: relative; position: relative;
display: inline-block; display: inline-block;
flex-shrink: 1;
flex-grow: 1; flex-grow: 1;
max-width: 100%; max-width: 100%;
} }
@@ -175,7 +251,7 @@
#fetchingText { #fetchingText {
visibility: hidden; visibility: hidden;
} }
@media only screen and (max-width: 768px) { @media only screen and (max-width: 1366px) {
main { main {
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
@@ -184,7 +260,7 @@
stroke-width: 0.1; stroke-width: 0.1;
} }
.translationText, .romanizationText { .translationText, .romanizationText {
font-size: 0.7em; font-size: 0.8em;
} }
.languageText { .languageText {
font-size: 0.6em; font-size: 0.6em;
@@ -192,6 +268,20 @@
} }
/* @media only screen and (max-width: 768px) {
.translationText, .romanizationText {
font-size: 0.8em;
}
.languageText {
font-size: 0.6em;
}
} */
p.bottom-of-page {
padding-top: 1em;
text-align: center;
font-size: 1.15em;
color: #3D3C3A;
}
</style> </style>
</head> </head>
<body> <body>
@@ -200,14 +290,23 @@
<h1>Indian Translate</h1> <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"> <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> <label for="query">Enter text to translate:</label>
<input type="text" name="query" id="query" required/> <input type="text" maxlength="20" name="query" id="query" required/>
<input type="submit" value="Translate"/> <input type="submit" id="submitButton" value="Translate"/>
</form> </form>
<progress id="loading-screen" class="loading-indicator"></progress> <progress id="loading-screen" class="loading-indicator"></progress>
<h3 id="fetchingText">Fetching translations...</h3> <h3 id="fetchingText">Fetching translations...</h3>
<noscript> <noscript>
<h2>This website requires javascript to work.</h2> <h2>This website requires javascript to work.</h2>
</noscript> </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>
<li>This project was inspired by the <a href="https://ukdataexplorer.com/european-translator/">European Translation Map</a>, as seen on Hacker News.</li>
</ul>
<p class="bottom-of-page">Made with love by <a href="https://twomorecents.org">Aadhavan Srinivasan</a></p>
</section> </section>
<section id="svgContainer"> <section id="svgContainer">

102
index.js
View File

@@ -1,28 +1,28 @@
const defaultColor = "#555555" const defaultColor = "#555555"
const languages = { const languages = {
tamil: {name: "Tamil", color: "#75d795", code: "ta", districts: []}, tamil: {name: "Tamil", color: "#75d795", code: "ta", text_align: "start", districts: []},
malayalam: {name: "Malayalam", color: "#ff7c7c", code: "ml", districts: []}, malayalam: {name: "Malayalam", color: "#ff7c7c", code: "ml", text_align: "end", districts: []},
kannada: {name: "Kannada", color: "#ffe77c", code: "kn", districts: []}, kannada: {name: "Kannada", color: "#ffe77c", code: "kn", text_align: "middle", districts: []},
telugu: {name: "Telugu", color: "#7c9dff", code: "te", districts: []}, telugu: {name: "Telugu", color: "#7c9dff", code: "te", text_align: "start", districts: []},
marathi: {name: "Marathi", color: "#e0ff7c", code: "mr", districts: []}, marathi: {name: "Marathi", color: "#e0ff7c", code: "mr", text_align: "middle", districts: []},
konkani: {name: "Konkani", color: "#9b7cff", code: "gom", districts: []}, konkani: {name: "Konkani", color: "#9b7cff", code: "gom", text_align: "end", districts: []},
hindi: {name: "Hindi", color: "#d17cff", code: "hi", districts: []}, hindi: {name: "Hindi", color: "#d17cff", code: "hi", text_align: "middle", districts: []},
gujarati: {name: "Gujarati", color: "#7cffee", code: "gu", districts: []}, gujarati: {name: "Gujarati", color: "#7cffee", code: "gu", text_align: "middle", districts: []},
oriya: {name: "Oriya", color: "#9bcc9f", code: "or", districts: []}, oriya: {name: "Oriya", color: "#9bcc9f", code: "or", text_align: "middle", districts: []},
bengali: {name: "Bengali", color: "#bf9a77", code: "bn", districts: []}, bengali: {name: "Bengali", color: "#bf9a77", code: "bn", text_align: "middle", districts: []},
punjabi: {name: "Punjabi", color: "#e84a35", code: "pa", districts: []}, punjabi: {name: "Punjabi", color: "#e84a35", code: "pa", text_align: "middle", districts: []},
mizo: {name: "Mizo", color: "#a6a4de", code: "lus", districts: []}, mizo: {name: "Mizo", color: "#a6a4de", code: "lus", text_align: "middle", districts: []},
assamese: {name: "Assamese", color: "#c9535b", code: "as", districts: []}, assamese: {name: "Assamese", color: "#c9535b", code: "as", text_align: "middle", districts: []},
bhojpuri: {name: "Bhojpuri", color: "#b3b876", code: "bho", districts: []}, bhojpuri: {name: "Bhojpuri", color: "#b3b876", code: "bho", text_align: "end", districts: []},
manipuri: {name: "Manipuri", color: "#c9afad", code: "mni-Mtei", districts: []}, manipuri: {name: "Manipuri", color: "#c9afad", code: "mni-Mtei", text_align: "middle", districts: []},
dogri: {name: "Dogri", color: "#9595e6", code: "doi", districts: []}, dogri: {name: "Dogri", color: "#9595e6", code: "doi", text_align: "middle", districts: []},
nepali: {name: "Nepali", color: "#71998e", code: "ne", districts: []}, nepali: {name: "Nepali", color: "#71998e", code: "ne", text_align: "middle", districts: []},
urdu: {name: "Urdu", color: "#3fa179", code: "ur", districts: []}, urdu: {name: "Urdu", color: "#3fa179", code: "ur", text_align: "middle", districts: []},
tulu: {name: "Tulu", color: "#dedc52", code: "tcy", districts: []}, tulu: {name: "Tulu", color: "#dedc52", code: "tcy", text_align: "end", districts: []},
maithali: {name: "Maithali", color: "#4472a6", code: "mai", districts: []}, maithali: {name: "Maithali", color: "#4472a6", code: "mai", text_align: "middle", districts: []},
sindhi: {name: "Sindhi", color: "#e89931", code: "sd", districts: []}, sindhi: {name: "Sindhi", color: "#e89931", code: "sd", text_align: "middle", districts: []},
awadhi: {name: "Awadhi", color: "#847fb5", code: "awa", districts: []}, awadhi: {name: "Awadhi", color: "#847fb5", code: "awa", text_align: "middle", districts: []},
}; };
// Credit: https://www.artcraftblend.com/blogs/colors/shades-of-pastel // Credit: https://www.artcraftblend.com/blogs/colors/shades-of-pastel
@@ -213,9 +213,14 @@ function stateOrDistrictOrLanguage(d) {
// const mapWidth = document.getElementById("indiaMap").getAttribute("width") // const mapWidth = document.getElementById("indiaMap").getAttribute("width")
// const mapHeight = document.getElementById("indiaMap").getAttribute("height") // const mapHeight = document.getElementById("indiaMap").getAttribute("height")
const mapWidth = /*window.innerWidth - */document.querySelector("#svgContainer").offsetWidth * 0.85; let mapWidth = /*window.innerWidth - */document.querySelector("#svgContainer").offsetWidth * 0.85;
// const mapHeight = document.querySelector("#svgContainer").offsetHeight; // const mapHeight = document.querySelector("#svgContainer").offsetHeight;
const mapHeight = (window.innerHeight - document.querySelector("#svgContainer").getBoundingClientRect().top); let mapHeight = (window.innerHeight - document.querySelector("#svgContainer").getBoundingClientRect().top);
if (window.innerWidth <= 768) {
mapWidth *= 1.5;
mapHeight *= 1.5;
}
const svg = d3.select("#svgContainer") const svg = d3.select("#svgContainer")
.append('svg') .append('svg')
@@ -227,7 +232,12 @@ const svg = d3.select("#svgContainer")
// .call(responsivefy); // .call(responsivefy);
function drawMap(world) { function drawMap(world) {
const projection = d3.geoMercator().fitSize([mapWidth, mapHeight], world) let projection = null;
if (window.innerWidth > 1366) {
projection = d3.geoMercator().fitSize([mapWidth, mapHeight], world)
} else {
projection = d3.geoMercator().fitWidth(mapWidth, world)
}
const path = d3.geoPath().projection(projection); const path = d3.geoPath().projection(projection);
requestAnimationFrame(() => { requestAnimationFrame(() => {
@@ -235,9 +245,9 @@ function drawMap(world) {
const bbox = newSvg.node().getBBox(); const bbox = newSvg.node().getBBox();
const originalWidth = +newSvg.attr("width"); const originalWidth = +newSvg.attr("width");
newSvg newSvg
// .attr("viewBox", `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`) .attr("viewBox", `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`)
.attr("viewBox", `0 ${bbox.y} ${originalWidth} ${bbox.height}`) // .attr("viewBox", `0 ${bbox.y} ${originalWidth} ${bbox.height}`)
// .attr("width", mapHeight.toString()) .attr("width", bbox.width)
.attr("height", bbox.height) .attr("height", bbox.height)
// .style("display", "block") // .style("display", "block")
// .style("max-height", "100%"); // optional: keep it scalable in a flexbox // .style("max-height", "100%"); // optional: keep it scalable in a flexbox
@@ -286,7 +296,10 @@ function drawMap(world) {
rtv -= 20; rtv -= 20;
} }
if (d.properties.lang_name == "Tamil") { if (d.properties.lang_name == "Tamil") {
rtv += 20; rtv -= 10;
}
if (d.properties.lang_name == "Kannada" && window.innerWidth <= 768) {
rtv += 15;
} }
if (d.properties.lang_name == "Maithali") { if (d.properties.lang_name == "Maithali") {
rtv += 10; rtv += 10;
@@ -304,10 +317,15 @@ function drawMap(world) {
if (stateOrDistrictOrLanguage(d) == "language") { if (stateOrDistrictOrLanguage(d) == "language") {
rtv = projection(d3.geoCentroid(d))[1] rtv = projection(d3.geoCentroid(d))[1]
if (d.properties.lang_name == "Kannada") { if (d.properties.lang_name == "Kannada") {
rtv += 15; if (window.innerWidth > 768) {
rtv += 10;
}
} }
if (d.properties.lang_name == "Tamil") { if (d.properties.lang_name == "Tamil") {
rtv -= 20; rtv -= 10;
}
if (d.properties.lang_name == "Malayalam") {
rtv += 10;
} }
if (d.properties.lang_name == "Gujarati") { if (d.properties.lang_name == "Gujarati") {
rtv -= 10; rtv -= 10;
@@ -321,12 +339,15 @@ function drawMap(world) {
if (d.properties.lang_name == "Bengali") { if (d.properties.lang_name == "Bengali") {
rtv += 25; rtv += 25;
} }
if (d.properties.lang_name == "Hindi") {
if (window.innerWidth > 768) {
rtv += 3 * parseFloat(getComputedStyle(document.documentElement).fontSize); // rem
}
}
return rtv return rtv
} }
}) })
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("class", "translationText") .attr("class", "translationText")
.attr("id", function(d) { .attr("id", function(d) {
if (stateOrDistrictOrLanguage(d) == "language") { if (stateOrDistrictOrLanguage(d) == "language") {
@@ -341,7 +362,9 @@ function drawMap(world) {
} else { } else {
d3.select(this).remove() // Only add this attribute if the element is a language d3.select(this).remove() // Only add this attribute if the element is a language
} }
}); })
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
.attr("fill", "black")
// Romanization // Romanization
textItems.append("text") textItems.append("text")
@@ -351,8 +374,6 @@ function drawMap(world) {
.attr("y", d => stateOrDistrictOrLanguage(d) == "language" ? .attr("y", d => stateOrDistrictOrLanguage(d) == "language" ?
parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) + parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) : parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) + parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) :
projection(d3.geoCentroid(d))[1]) projection(d3.geoCentroid(d))[1])
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("class", "romanizationText") .attr("class", "romanizationText")
.attr("id", function(d) { .attr("id", function(d) {
if (stateOrDistrictOrLanguage(d) == "language") { if (stateOrDistrictOrLanguage(d) == "language") {
@@ -365,7 +386,9 @@ function drawMap(world) {
if (!stateOrDistrictOrLanguage(d) == "language") { if (!stateOrDistrictOrLanguage(d) == "language") {
d3.select(this).remove() // Only add this attribute if the element is a language d3.select(this).remove() // Only add this attribute if the element is a language
} }
}); })
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
.attr("fill", "black")
// Language // Language
textItems.append("text") textItems.append("text")
@@ -375,8 +398,6 @@ function drawMap(world) {
.attr("y", d => stateOrDistrictOrLanguage(d) == "language" ? .attr("y", d => stateOrDistrictOrLanguage(d) == "language" ?
parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) - parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) : parseFloat(document.getElementById(d.properties.lang_code + "Text").getAttribute("y")) - parseFloat(getComputedStyle(document.getElementsByClassName('translationText')[0]).getPropertyValue('font-size')) :
projection(d3.geoCentroid(d))[1]) projection(d3.geoCentroid(d))[1])
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("class", "languageText") .attr("class", "languageText")
.attr("id", function(d) { .attr("id", function(d) {
if (stateOrDistrictOrLanguage(d) == "language") { if (stateOrDistrictOrLanguage(d) == "language") {
@@ -397,6 +418,9 @@ function drawMap(world) {
d3.select(this).remove() // Only add this attribute if the element is a language d3.select(this).remove() // Only add this attribute if the element is a language
} }
}) })
.attr("text-anchor", d => typeof d.properties.lang_name != "undefined" && languages[d.properties.lang_name.toLowerCase()].text_align)
.attr("fill", "black")
let allLangs = [] let allLangs = []
const coordinates = [77.69916967457782,23.389970772934166]; const coordinates = [77.69916967457782,23.389970772934166];

Binary file not shown.