A paying customer in Denmark pasted Danish lyrics into our AI song generator today. The song came back sung in English.
Nothing crashed. The code did exactly what it was written to do, and that is the interesting part.
How "Auto" picked a language
SongUp AI sings in 76 languages, and most people never open the language menu. So "Auto" has to guess. For lyrics someone wrote themselves, the old rule was:
- A language named in the description ("a rock song in Hindi")
- The lyrics' alphabet (Arabic, Devanagari, Hangul, Thai…)
- Otherwise, English
Step 2 is great for Urdu, Hindi or Korean. It is useless for Danish, German, Spanish, Polish or Swahili: they all use the Latin alphabet, so they fell straight through to English.
The fix: three cheap signals, in order
export function autoSongLanguage({ prompt, lyrics, acceptLanguage, country }) {
const named = languageNamedInPrompt(prompt)
|| scriptLanguage(lyrics, country)
|| scriptLanguage(prompt, country);
if (named) return named;
// 1. Words only one language uses: "nu", "endnu", "hvid" are Danish, "meg"/"deg" Norwegian.
const words = languageFromFunctionWords(lyrics);
if (words) return words;
// 2. Lyrics that plainly aren't English: trust the browser language, then the country.
if (!looksEnglish(lyrics)) {
return nonEnglishLocale(acceptLanguage) || countryLanguage(country) || 'English';
}
return 'English';
}
looksEnglish is deliberately dumb: split into words and check how many are among ~35 very common English words (the, and, you, my, love, heart…). If fewer than one word in ten is, the text isn't English.
export function looksEnglish(text: string): boolean {
const words = text.toLowerCase().split(/[^\p{L}']+/u).filter(Boolean);
if (words.length < 4) return true;
const hits = words.filter((w) => ENGLISH_MARKERS.has(w)).length;
return hits / words.length >= 0.1;
}
Two details mattered:
- The country only counts when the lyrics aren't English. An English love song written in Mexico must stay English. Only Danish-looking lyrics from Denmark become Danish.
- Close neighbours need their own tie-breaks. Danish and Norwegian share jeg, ikke and og, so each list only holds the words the other spells differently. Roman Urdu and Roman Hindi share almost everything, so in Pakistan the answer is Urdu.
The test table that caught the gaps
| Lyrics | Browser | Country | Expected |
|---|---|---|---|
| Danish lyrics | da-DK | DK | Danish |
| Danish lyrics | (none) | DK | Danish |
| English love song | da-DK | DK | English |
| "Te quiero mucho mi amor…" | en-US | MX | Spanish |
| "Mera dil tera hai…" | en-US | PK | Urdu |
| "Mera dil tera hai…" | en-US | IN | Hindi |
The first version failed three of these. The table is now a regression test.
Takeaways
- Script detection covers maybe a third of the world's languages. For the rest, a short list of distinctive words beats a heavy language-ID model for text this short.
- Use location as a tie-breaker, never as the first signal.
- When a paying user gets the wrong language, it's a quality bug, not an edge case.
If you want to see it working, paste lyrics in your own language into the song generator. The full list of languages is at songupai.com/languages.
Top comments (0)