Compare commits

...

5 Commits

6 changed files with 150 additions and 86 deletions

View File

@@ -15,6 +15,8 @@ require (
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // 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/otel v1.29.0 // indirect

View File

@@ -10,6 +10,7 @@ cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0
cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
cloud.google.com/go/translate v1.12.3 h1:XJ7LipYJi80BCgVk2lx1fwc7DIYM6oV2qx1G4IAGQ5w=
cloud.google.com/go/translate v1.12.3/go.mod h1:qINOVpgmgBnY4YTFHdfVO4nLrSBlpvlIyosqpGEgyEg=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
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=
@@ -17,12 +18,19 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
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/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
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/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/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
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/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=

View File

@@ -2,17 +2,49 @@ package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
translate "cloud.google.com/go/translate/apiv3"
"cloud.google.com/go/translate/apiv3/translatepb"
)
const project_id string = "india-translate-testing-452100"
type translationStruct struct {
En string `db:"english" json:"en"`
Hi string `db:"hindi" json:"hi"`
Bn string `db:"bengali" json:"bn"`
Mr string `db:"marathi" json:"mr"`
Ta string `db:"tamil" json:"ta"`
Te string `db:"telugu" json:"te"`
Ml string `db:"malayalam" json:"ml"`
Kn string `db:"kannada" json:"kn"`
Gu string `db:"gujarati" json:"gu"`
Or string `db:"oriya" json:"or"`
Ur string `db:"urdu" json:"ur"`
Lus string `db:"mizo" json:"lus"`
As string `db:"assamese" json:"as"`
Pa string `db:"punjabi" json:"pa"`
Mai string `db:"maithili" json:"mai"`
Mwr string `db:"marwari" json:"mwr"`
Sat string `db:"santali" json:"sat"`
Ne string `db:"nepali" json:"ne"`
Gom string `db:"konkani" json:"gom"`
Tcy string `db:"tulu" json:"tcy"`
Bho string `db:"bhojpuri" json:"bho"`
Doi string `db:"dogri" json:"doi"`
Mni_mtei string `db:"manipuri" json:"mni_mtei"`
Sd string `db:"sindhi" json:"sd"`
Awa string `db:"awadhi" json:"awa"`
}
var lang_codes []string = []string{
"hi", // Hindi
"bn", // Bengali
@@ -40,6 +72,39 @@ var lang_codes []string = []string{
"awa", // Awadhi
}
var db *sqlx.DB
/*
Returns the cached translation from the database, for the given english text. The first parameter
indicates whether or not the translation exists.
*/
func getCachedTranslation(data string) (bool, translationStruct) {
prepared, err := db.Preparex("SELECT * from TRANSLATIONS WHERE english = ? COLLATE NOCASE")
if err != nil {
panic(err)
}
translations := translationStruct{}
err = prepared.Get(&translations, data)
if err != nil {
if err == sql.ErrNoRows {
return false, translations
} else {
panic(err)
}
} else {
return true, translations
}
}
func addToDatabase(translation translationStruct) {
_, err := db.NamedExec(`INSERT INTO translations VALUES (:english, :hindi, :bengali, :marathi, :tamil, :telugu, :kannada, :malayalam, :oriya, :gujarati, :marwari, :urdu, :mizo, :assamese, :punjabi, :maithili, :santali, :nepali, :konkani, :tulu, :bhojpuri, :dogri, :manipuri, :sindhi, :awadhi)`, &translation)
if err != nil {
panic(err)
}
}
func translateText(text string, targetLang string) (result string, err error) {
return translateTextHelper(project_id, "en-US", targetLang, text)
}
@@ -80,22 +145,39 @@ func handler(w http.ResponseWriter, r *http.Request) {
queries := r.URL.Query()
toTranslate := queries["query"][0]
langToTranslation := make(map[string]string)
for _, lang_code := range lang_codes {
translation, err := translateText(toTranslate, lang_code)
if ok, translation := getCachedTranslation(toTranslate); ok {
translationJson, _ := json.Marshal(translation)
fmt.Fprintf(w, "%v", string(translationJson))
} else {
langToTranslation := make(map[string]string)
for _, lang_code := range lang_codes {
translation, err := translateText(toTranslate, lang_code)
if err != nil {
panic(err)
}
langToTranslation[lang_code] = translation
}
langToTranslationJson, _ := json.Marshal(langToTranslation)
translation := translationStruct{}
err := json.Unmarshal(langToTranslationJson, &translation)
translation.En = toTranslate // langToTranslation doesn't contain the english value
addToDatabase(translation)
if err != nil {
panic(err)
}
langToTranslation[lang_code] = translation
fmt.Fprintf(w, "%v", string(langToTranslationJson))
}
langToTranslationJson, _ := json.Marshal(langToTranslation)
fmt.Fprintf(w, "%v", string(langToTranslationJson))
// fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
fmt.Printf("Starting server...")
var err error
db, err = sqlx.Connect("sqlite3", "translations.db")
if err != nil {
panic(err)
}
defer db.Close()
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":9090", nil))
}

Binary file not shown.

125
index.js
View File

@@ -1,57 +1,32 @@
const svg = d3.select("svg")
const tamilColor = "#75d795" // Tamil
const malayalamColor = "#ff7c7c" // Malayalam
const kannadaColor = "#ffe77c" // Kannada
const teluguColor = "#7c9dff" // Telugu
const marathiColor = "#e0ff7c" // Marathi
const konkaniColor = "#9b7cff" // Konkani
const hindiColor = "#d17cff" // Hindi
const gujaratiColor = "#7cffee" // Gujarati
const marwariColor = "#7bc4c9" // Marwari
const oriyaColor = "#9bcc9f" // Oriya
const bengaliColor = "#bf9a77" // Bengali
const punjabiColor = "#e84a35" // Punjabi
const mizoColor = "#a6a4de" // Mizo
const assameseColor = "#c9535b" // Assamese
const bhojpuriColor = "#b3b876" // Bhojpuri
const manipuriColor = "#c9afad" // Manipuri
const dogriColor = "#9595e6" // Dogri (near Kashmir)
const nepaliColor = "#71998e" // Nepali
const urduColor = "#3fa179" // Urdu
const tuluColor = "#dedc52" // Tulu
const maithaliColor = "#4472a6" // Maithali
const santaliColor = "#96bf60" // Santhali
const sindhiColor = "#e89931" // Sindhi
const awadhiColor = "#847fb5" // Awadhi
const defaultColor = "#555555"
const languages = {
tamil: {name: "Tamil", color: tamilColor, code: "ta", districts: []},
malayalam: {name: "Malayalam", color: malayalamColor, code: "ml", districts: []},
kannada: {name: "Kannada", color: kannadaColor, code: "kn", districts: []},
telugu: {name: "Telugu", color: teluguColor, code: "te", districts: []},
marathi: {name: "Marathi", color: marathiColor, code: "mr", districts: []},
konkani: {name: "Konkani", color: konkaniColor, code: "gom", districts: []},
hindi: {name: "Hindi", color: hindiColor, code: "hi", districts: []},
gujarati: {name: "Gujarati", color: gujaratiColor, code: "gu", districts: []},
marwari: {name: "Marwari", color: marwariColor, code: "mwr", districts: []},
oriya: {name: "Oriya", color: oriyaColor, code: "or", districts: []},
bengali: {name: "Bengali", color: bengaliColor, code: "bn", districts: []},
punjabi: {name: "Punjabi", color: punjabiColor, code: "pa", districts: []},
mizo: {name: "Mizo", color: mizoColor, code: "lus", districts: []},
assamese: {name: "Assamese", color: assameseColor, code: "as", districts: []},
bhojpuri: {name: "Bhojpuri", color: bhojpuriColor, code: "bho", districts: []},
manipuri: {name: "Manipuri", color: manipuriColor, code: "mni-Mtei", districts: []},
dogri: {name: "Dogri", color: dogriColor, code: "doi", districts: []},
nepali: {name: "Nepali", color: nepaliColor, code: "ne", districts: []},
urdu: {name: "Urdu", color: urduColor, code: "ur", districts: []},
tulu: {name: "Tulu", color: tuluColor, code: "tcy", districts: []},
maithali: {name: "Maithali", color: maithaliColor, code: "mai", districts: []},
santali: {name: "Santali", color: santaliColor, code: "sat", districts: []},
sindhi: {name: "Sindhi", color: sindhiColor, code: "sd", districts: []},
awadhi: {name: "Awadhi", color: awadhiColor, code: "awa", districts: []},
tamil: {name: "Tamil", color: "#75d795", code: "ta", districts: []},
malayalam: {name: "Malayalam", color: "#ff7c7c", code: "ml", districts: []},
kannada: {name: "Kannada", color: "#ffe77c", code: "kn", districts: []},
telugu: {name: "Telugu", color: "#7c9dff", code: "te", districts: []},
marathi: {name: "Marathi", color: "#e0ff7c", code: "mr", districts: []},
konkani: {name: "Konkani", color: "#9b7cff", code: "gom", districts: []},
hindi: {name: "Hindi", color: "#d17cff", code: "hi", districts: []},
gujarati: {name: "Gujarati", color: "#7cffee", code: "gu", districts: []},
marwari: {name: "Marwari", color: "#7bc4c9", code: "mwr", districts: []},
oriya: {name: "Oriya", color: "#9bcc9f", code: "or", districts: []},
bengali: {name: "Bengali", color: "#bf9a77", code: "bn", districts: []},
punjabi: {name: "Punjabi", color: "#e84a35", code: "pa", districts: []},
mizo: {name: "Mizo", color: "#a6a4de", code: "lus", districts: []},
assamese: {name: "Assamese", color: "#c9535b", code: "as", districts: []},
bhojpuri: {name: "Bhojpuri", color: "#b3b876", code: "bho", districts: []},
manipuri: {name: "Manipuri", color: "#c9afad", code: "mni-Mtei", districts: []},
dogri: {name: "Dogri", color: "#9595e6", code: "doi", districts: []},
nepali: {name: "Nepali", color: "#71998e", code: "ne", districts: []},
urdu: {name: "Urdu", color: "#3fa179", code: "ur", districts: []},
tulu: {name: "Tulu", color: "#dedc52", code: "tcy", districts: []},
maithali: {name: "Maithali", color: "#4472a6", code: "mai", districts: []},
santali: {name: "Santali", color: "#96bf60", code: "sat", districts: []},
sindhi: {name: "Sindhi", color: "#e89931", code: "sd", districts: []},
awadhi: {name: "Awadhi", color: "#847fb5", code: "awa", districts: []},
};
// Credit: https://www.artcraftblend.com/blogs/colors/shades-of-pastel
@@ -89,7 +64,6 @@ const state2lang = {
"Lakshadweep": languages["malayalam"],
"Delhi": languages["hindi"],
"Chandigarh": languages["hindi"]
}
const district2lang = { // Should override state colors
@@ -143,7 +117,7 @@ const district2lang = { // Should override state colors
"Hapur": languages["urdu"],
"Kutch": languages["sindhi"],
"Godda": languages["santali"],
"Deoghar": languages["santali"],
"Dumka": languages["santali"],
@@ -166,14 +140,12 @@ const district2lang = { // Should override state colors
"Rae Bareli": languages["awadhi"],
"Amethi": languages["awadhi"],
"Bahraich": languages["awadhi"],
}
// Functions for calculating and dealing with language boundaries
function reverseCoordArrays(coords) {
if (!Array.isArray(coords)) {
return coords;
return coords;
}
if (coords.every(item => Array.isArray(item) && item.length == 2 && item.every(val => Number.isFinite(val)))) {
if (!turf.booleanClockwise(coords)) {
@@ -186,14 +158,13 @@ function reverseCoordArrays(coords) {
return coords.map(reverseCoordArrays);
}
function getOuterBoundaryPolygon(features) {
// Check if we have features to process
if (!features || features.length === 0) {
console.warn("No features to process for boundary");
return null;
}
// Handle single feature case
if (features.length === 1) {
return features[0];
@@ -205,6 +176,15 @@ function getOuterBoundaryPolygon(features) {
return combined;
}
function district2langFunc(d) {
if (district2lang.hasOwnProperty(d.properties.district)) {
return district2lang[d.properties.district];
} else if (state2lang.hasOwnProperty(d.properties.st_nm)) {
return state2lang[d.properties.st_nm];
} else {
return undefined;
}
}
function stateOrDistrictOrLanguage(d) {
if (typeof d.properties.district !== 'undefined') {
@@ -233,24 +213,18 @@ function drawMap(world) {
.attr("d", path)
.attr("class", d => stateOrDistrictOrLanguage(d))
.attr("fill", function(d) {
if (stateOrDistrictOrLanguage(d) === "district") {
if (district2lang.hasOwnProperty(d.properties.district)) {
return district2lang[d.properties.district].color;
} else if (state2lang.hasOwnProperty(d.properties.st_nm)) {
return state2lang[d.properties.st_nm].color;
} else {
return defaultColor;
}
}
if (stateOrDistrictOrLanguage(d) === "district") {
const districtLang = district2langFunc(d)
if (typeof districtLang !== 'undefined') {
return districtLang.color
} else {
return defaultColor;
}
}
})
.each(function(d) {
if (stateOrDistrictOrLanguage(d) === "district") {
let districtLang;
if (district2lang.hasOwnProperty(d.properties.district)) {
districtLang = district2lang[d.properties.district];
} else if (state2lang.hasOwnProperty(d.properties.st_nm)) {
districtLang = state2lang[d.properties.st_nm];
}
const districtLang = district2langFunc(d);
if (typeof districtLang !== 'undefined') {
districtLang.districts.push(d)
}
@@ -277,7 +251,7 @@ function drawMap(world) {
if (stateOrDistrictOrLanguage(d) == "language") {
return d.properties.lang_name;
} else {
d3.select(this).remove() // Only add text if the element is a language
d3.select(this).remove() // Only add this attribute if the element is a language
}
});
@@ -285,7 +259,7 @@ function drawMap(world) {
const coordinates = [77.69916967457782,23.389970772934166];
const [xCoord, yCoord] = projection(coordinates);
svg.append("text")
.attr("x", xCoord)
.attr("y", yCoord)
@@ -299,7 +273,7 @@ function drawMap(world) {
// "type": "FeatureCollection",
// "features": lang.districts
// };
//
//
// let outerBound = getOuterBoundaryPolygon(geojson.features)
// outerBound["id"] = "lang" + lang.name
// outerBound.properties["lang_name"]= lang.name
@@ -318,4 +292,3 @@ function drawMap(world) {
}
d3.json("india_with_districts_with_languages.json").then(drawMap)

View File

@@ -1,5 +1,4 @@
1. REFACTOR
2. Cache results in a database instead of fetching them each time, use cached results if possible
3. Figure out positioning of the different translations, show all of them instead of having to hover
4. Show romanizations
5. General beautification