Efficiently replace all accented characters in a string?

JavascriptSortingStringCollation

Javascript Problem Overview


For a poor man's implementation of near-collation-correct sorting on the client side I need a JavaScript function that does efficient single character replacement in a string.

Here is what I mean (note that this applies to German text, other languages sort differently):

native sorting gets it wrong: a b c o u z ä ö ü
collation-correct would be:   a ä b c o ö u ü z

Basically, I need all occurrences of "ä" of a given string replaced with "a" (and so on). This way the result of native sorting would be very close to what a user would expect (or what a database would return).

Other languages have facilities to do just that: Python supplies str.translate(), in Perl there is tr/…/…/, XPath has a function translate(), ColdFusion has ReplaceList(). But what about JavaScript?

Here is what I have right now.

// s would be a rather short string (something like 
// 200 characters at max, most of the time much less)
function makeSortString(s) {
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  var translate_re = /[öäüÖÄÜ]/g;
  return ( s.replace(translate_re, function(match) { 
    return translate[match]; 
  }) );
}

For starters, I don't like the fact that the regex is rebuilt every time I call the function. I guess a closure can help in this regard, but I don't seem to get the hang of it for some reason.

Can someone think of something more efficient?


Answers below fall in two categories:

  1. String replacement functions of varying degrees of completeness and efficiency (what I was originally asking about)
  2. A late mention of String#localeCompare, which is now widely supported among JS engines (not so much at the time of the question) and could solve this category of problem much more elegantly.

Javascript Solutions


Solution 1 - Javascript

Here is a more complete version based on the Unicode standard.

var Latinise={};Latinise.latin_map={"Á":"A",
"Ă":"A",
"Ắ":"A",
"Ặ":"A",
"Ằ":"A",
"Ẳ":"A",
"Ẵ":"A",
"Ǎ":"A",
"Â":"A",
"Ấ":"A",
"Ậ":"A",
"Ầ":"A",
"Ẩ":"A",
"Ẫ":"A",
"Ä":"A",
"Ǟ":"A",
"Ȧ":"A",
"Ǡ":"A",
"Ạ":"A",
"Ȁ":"A",
"À":"A",
"Ả":"A",
"Ȃ":"A",
"Ā":"A",
"Ą":"A",
"Å":"A",
"Ǻ":"A",
"Ḁ":"A",
"Ⱥ":"A",
"Ã":"A",
"Ꜳ":"AA",
"Æ":"AE",
"Ǽ":"AE",
"Ǣ":"AE",
"Ꜵ":"AO",
"Ꜷ":"AU",
"Ꜹ":"AV",
"Ꜻ":"AV",
"Ꜽ":"AY",
"Ḃ":"B",
"Ḅ":"B",
"Ɓ":"B",
"Ḇ":"B",
"Ƀ":"B",
"Ƃ":"B",
"Ć":"C",
"Č":"C",
"Ç":"C",
"Ḉ":"C",
"Ĉ":"C",
"Ċ":"C",
"Ƈ":"C",
"Ȼ":"C",
"Ď":"D",
"Ḑ":"D",
"Ḓ":"D",
"Ḋ":"D",
"Ḍ":"D",
"Ɗ":"D",
"Ḏ":"D",
"Dz":"D",
"Dž":"D",
"Đ":"D",
"Ƌ":"D",
"DZ":"DZ",
"DŽ":"DZ",
"É":"E",
"Ĕ":"E",
"Ě":"E",
"Ȩ":"E",
"Ḝ":"E",
"Ê":"E",
"Ế":"E",
"Ệ":"E",
"Ề":"E",
"Ể":"E",
"Ễ":"E",
"Ḙ":"E",
"Ë":"E",
"Ė":"E",
"Ẹ":"E",
"Ȅ":"E",
"È":"E",
"Ẻ":"E",
"Ȇ":"E",
"Ē":"E",
"Ḗ":"E",
"Ḕ":"E",
"Ę":"E",
"Ɇ":"E",
"Ẽ":"E",
"Ḛ":"E",
"Ꝫ":"ET",
"Ḟ":"F",
"Ƒ":"F",
"Ǵ":"G",
"Ğ":"G",
"Ǧ":"G",
"Ģ":"G",
"Ĝ":"G",
"Ġ":"G",
"Ɠ":"G",
"Ḡ":"G",
"Ǥ":"G",
"Ḫ":"H",
"Ȟ":"H",
"Ḩ":"H",
"Ĥ":"H",
"Ⱨ":"H",
"Ḧ":"H",
"Ḣ":"H",
"Ḥ":"H",
"Ħ":"H",
"Í":"I",
"Ĭ":"I",
"Ǐ":"I",
"Î":"I",
"Ï":"I",
"Ḯ":"I",
"İ":"I",
"Ị":"I",
"Ȉ":"I",
"Ì":"I",
"Ỉ":"I",
"Ȋ":"I",
"Ī":"I",
"Į":"I",
"Ɨ":"I",
"Ĩ":"I",
"Ḭ":"I",
"Ꝺ":"D",
"Ꝼ":"F",
"Ᵹ":"G",
"Ꞃ":"R",
"Ꞅ":"S",
"Ꞇ":"T",
"Ꝭ":"IS",
"Ĵ":"J",
"Ɉ":"J",
"Ḱ":"K",
"Ǩ":"K",
"Ķ":"K",
"Ⱪ":"K",
"Ꝃ":"K",
"Ḳ":"K",
"Ƙ":"K",
"Ḵ":"K",
"Ꝁ":"K",
"Ꝅ":"K",
"Ĺ":"L",
"Ƚ":"L",
"Ľ":"L",
"Ļ":"L",
"Ḽ":"L",
"Ḷ":"L",
"Ḹ":"L",
"Ⱡ":"L",
"Ꝉ":"L",
"Ḻ":"L",
"Ŀ":"L",
"Ɫ":"L",
"Lj":"L",
"Ł":"L",
"LJ":"LJ",
"Ḿ":"M",
"Ṁ":"M",
"Ṃ":"M",
"Ɱ":"M",
"Ń":"N",
"Ň":"N",
"Ņ":"N",
"Ṋ":"N",
"Ṅ":"N",
"Ṇ":"N",
"Ǹ":"N",
"Ɲ":"N",
"Ṉ":"N",
"Ƞ":"N",
"Nj":"N",
"Ñ":"N",
"NJ":"NJ",
"Ó":"O",
"Ŏ":"O",
"Ǒ":"O",
"Ô":"O",
"Ố":"O",
"Ộ":"O",
"Ồ":"O",
"Ổ":"O",
"Ỗ":"O",
"Ö":"O",
"Ȫ":"O",
"Ȯ":"O",
"Ȱ":"O",
"Ọ":"O",
"Ő":"O",
"Ȍ":"O",
"Ò":"O",
"Ỏ":"O",
"Ơ":"O",
"Ớ":"O",
"Ợ":"O",
"Ờ":"O",
"Ở":"O",
"Ỡ":"O",
"Ȏ":"O",
"Ꝋ":"O",
"Ꝍ":"O",
"Ō":"O",
"Ṓ":"O",
"Ṑ":"O",
"Ɵ":"O",
"Ǫ":"O",
"Ǭ":"O",
"Ø":"O",
"Ǿ":"O",
"Õ":"O",
"Ṍ":"O",
"Ṏ":"O",
"Ȭ":"O",
"Ƣ":"OI",
"Ꝏ":"OO",
"Ɛ":"E",
"Ɔ":"O",
"Ȣ":"OU",
"Ṕ":"P",
"Ṗ":"P",
"Ꝓ":"P",
"Ƥ":"P",
"Ꝕ":"P",
"Ᵽ":"P",
"Ꝑ":"P",
"Ꝙ":"Q",
"Ꝗ":"Q",
"Ŕ":"R",
"Ř":"R",
"Ŗ":"R",
"Ṙ":"R",
"Ṛ":"R",
"Ṝ":"R",
"Ȑ":"R",
"Ȓ":"R",
"Ṟ":"R",
"Ɍ":"R",
"Ɽ":"R",
"Ꜿ":"C",
"Ǝ":"E",
"Ś":"S",
"Ṥ":"S",
"Š":"S",
"Ṧ":"S",
"Ş":"S",
"Ŝ":"S",
"Ș":"S",
"Ṡ":"S",
"Ṣ":"S",
"Ṩ":"S",
"Ť":"T",
"Ţ":"T",
"Ṱ":"T",
"Ț":"T",
"Ⱦ":"T",
"Ṫ":"T",
"Ṭ":"T",
"Ƭ":"T",
"Ṯ":"T",
"Ʈ":"T",
"Ŧ":"T",
"Ɐ":"A",
"Ꞁ":"L",
"Ɯ":"M",
"Ʌ":"V",
"Ꜩ":"TZ",
"Ú":"U",
"Ŭ":"U",
"Ǔ":"U",
"Û":"U",
"Ṷ":"U",
"Ü":"U",
"Ǘ":"U",
"Ǚ":"U",
"Ǜ":"U",
"Ǖ":"U",
"Ṳ":"U",
"Ụ":"U",
"Ű":"U",
"Ȕ":"U",
"Ù":"U",
"Ủ":"U",
"Ư":"U",
"Ứ":"U",
"Ự":"U",
"Ừ":"U",
"Ử":"U",
"Ữ":"U",
"Ȗ":"U",
"Ū":"U",
"Ṻ":"U",
"Ų":"U",
"Ů":"U",
"Ũ":"U",
"Ṹ":"U",
"Ṵ":"U",
"Ꝟ":"V",
"Ṿ":"V",
"Ʋ":"V",
"Ṽ":"V",
"Ꝡ":"VY",
"Ẃ":"W",
"Ŵ":"W",
"Ẅ":"W",
"Ẇ":"W",
"Ẉ":"W",
"Ẁ":"W",
"Ⱳ":"W",
"Ẍ":"X",
"Ẋ":"X",
"Ý":"Y",
"Ŷ":"Y",
"Ÿ":"Y",
"Ẏ":"Y",
"Ỵ":"Y",
"Ỳ":"Y",
"Ƴ":"Y",
"Ỷ":"Y",
"Ỿ":"Y",
"Ȳ":"Y",
"Ɏ":"Y",
"Ỹ":"Y",
"Ź":"Z",
"Ž":"Z",
"Ẑ":"Z",
"Ⱬ":"Z",
"Ż":"Z",
"Ẓ":"Z",
"Ȥ":"Z",
"Ẕ":"Z",
"Ƶ":"Z",
"IJ":"IJ",
"Œ":"OE",
"ᴀ":"A",
"ᴁ":"AE",
"ʙ":"B",
"ᴃ":"B",
"ᴄ":"C",
"ᴅ":"D",
"ᴇ":"E",
"ꜰ":"F",
"ɢ":"G",
"ʛ":"G",
"ʜ":"H",
"ɪ":"I",
"ʁ":"R",
"ᴊ":"J",
"ᴋ":"K",
"ʟ":"L",
"ᴌ":"L",
"ᴍ":"M",
"ɴ":"N",
"ᴏ":"O",
"ɶ":"OE",
"ᴐ":"O",
"ᴕ":"OU",
"ᴘ":"P",
"ʀ":"R",
"ᴎ":"N",
"ᴙ":"R",
"ꜱ":"S",
"ᴛ":"T",
"ⱻ":"E",
"ᴚ":"R",
"ᴜ":"U",
"ᴠ":"V",
"ᴡ":"W",
"ʏ":"Y",
"ᴢ":"Z",
"á":"a",
"ă":"a",
"ắ":"a",
"ặ":"a",
"ằ":"a",
"ẳ":"a",
"ẵ":"a",
"ǎ":"a",
"â":"a",
"ấ":"a",
"ậ":"a",
"ầ":"a",
"ẩ":"a",
"ẫ":"a",
"ä":"a",
"ǟ":"a",
"ȧ":"a",
"ǡ":"a",
"ạ":"a",
"ȁ":"a",
"à":"a",
"ả":"a",
"ȃ":"a",
"ā":"a",
"ą":"a",
"ᶏ":"a",
"ẚ":"a",
"å":"a",
"ǻ":"a",
"ḁ":"a",
"ⱥ":"a",
"ã":"a",
"ꜳ":"aa",
"æ":"ae",
"ǽ":"ae",
"ǣ":"ae",
"ꜵ":"ao",
"ꜷ":"au",
"ꜹ":"av",
"ꜻ":"av",
"ꜽ":"ay",
"ḃ":"b",
"ḅ":"b",
"ɓ":"b",
"ḇ":"b",
"ᵬ":"b",
"ᶀ":"b",
"ƀ":"b",
"ƃ":"b",
"ɵ":"o",
"ć":"c",
"č":"c",
"ç":"c",
"ḉ":"c",
"ĉ":"c",
"ɕ":"c",
"ċ":"c",
"ƈ":"c",
"ȼ":"c",
"ď":"d",
"ḑ":"d",
"ḓ":"d",
"ȡ":"d",
"ḋ":"d",
"ḍ":"d",
"ɗ":"d",
"ᶑ":"d",
"ḏ":"d",
"ᵭ":"d",
"ᶁ":"d",
"đ":"d",
"ɖ":"d",
"ƌ":"d",
"ı":"i",
"ȷ":"j",
"ɟ":"j",
"ʄ":"j",
"dz":"dz",
"dž":"dz",
"é":"e",
"ĕ":"e",
"ě":"e",
"ȩ":"e",
"ḝ":"e",
"ê":"e",
"ế":"e",
"ệ":"e",
"ề":"e",
"ể":"e",
"ễ":"e",
"ḙ":"e",
"ë":"e",
"ė":"e",
"ẹ":"e",
"ȅ":"e",
"è":"e",
"ẻ":"e",
"ȇ":"e",
"ē":"e",
"ḗ":"e",
"ḕ":"e",
"ⱸ":"e",
"ę":"e",
"ᶒ":"e",
"ɇ":"e",
"ẽ":"e",
"ḛ":"e",
"ꝫ":"et",
"ḟ":"f",
"ƒ":"f",
"ᵮ":"f",
"ᶂ":"f",
"ǵ":"g",
"ğ":"g",
"ǧ":"g",
"ģ":"g",
"ĝ":"g",
"ġ":"g",
"ɠ":"g",
"ḡ":"g",
"ᶃ":"g",
"ǥ":"g",
"ḫ":"h",
"ȟ":"h",
"ḩ":"h",
"ĥ":"h",
"ⱨ":"h",
"ḧ":"h",
"ḣ":"h",
"ḥ":"h",
"ɦ":"h",
"ẖ":"h",
"ħ":"h",
"ƕ":"hv",
"í":"i",
"ĭ":"i",
"ǐ":"i",
"î":"i",
"ï":"i",
"ḯ":"i",
"ị":"i",
"ȉ":"i",
"ì":"i",
"ỉ":"i",
"ȋ":"i",
"ī":"i",
"į":"i",
"ᶖ":"i",
"ɨ":"i",
"ĩ":"i",
"ḭ":"i",
"ꝺ":"d",
"ꝼ":"f",
"ᵹ":"g",
"ꞃ":"r",
"ꞅ":"s",
"ꞇ":"t",
"ꝭ":"is",
"ǰ":"j",
"ĵ":"j",
"ʝ":"j",
"ɉ":"j",
"ḱ":"k",
"ǩ":"k",
"ķ":"k",
"ⱪ":"k",
"ꝃ":"k",
"ḳ":"k",
"ƙ":"k",
"ḵ":"k",
"ᶄ":"k",
"ꝁ":"k",
"ꝅ":"k",
"ĺ":"l",
"ƚ":"l",
"ɬ":"l",
"ľ":"l",
"ļ":"l",
"ḽ":"l",
"ȴ":"l",
"ḷ":"l",
"ḹ":"l",
"ⱡ":"l",
"ꝉ":"l",
"ḻ":"l",
"ŀ":"l",
"ɫ":"l",
"ᶅ":"l",
"ɭ":"l",
"ł":"l",
"lj":"lj",
"ſ":"s",
"ẜ":"s",
"ẛ":"s",
"ẝ":"s",
"ḿ":"m",
"ṁ":"m",
"ṃ":"m",
"ɱ":"m",
"ᵯ":"m",
"ᶆ":"m",
"ń":"n",
"ň":"n",
"ņ":"n",
"ṋ":"n",
"ȵ":"n",
"ṅ":"n",
"ṇ":"n",
"ǹ":"n",
"ɲ":"n",
"ṉ":"n",
"ƞ":"n",
"ᵰ":"n",
"ᶇ":"n",
"ɳ":"n",
"ñ":"n",
"nj":"nj",
"ó":"o",
"ŏ":"o",
"ǒ":"o",
"ô":"o",
"ố":"o",
"ộ":"o",
"ồ":"o",
"ổ":"o",
"ỗ":"o",
"ö":"o",
"ȫ":"o",
"ȯ":"o",
"ȱ":"o",
"ọ":"o",
"ő":"o",
"ȍ":"o",
"ò":"o",
"ỏ":"o",
"ơ":"o",
"ớ":"o",
"ợ":"o",
"ờ":"o",
"ở":"o",
"ỡ":"o",
"ȏ":"o",
"ꝋ":"o",
"ꝍ":"o",
"ⱺ":"o",
"ō":"o",
"ṓ":"o",
"ṑ":"o",
"ǫ":"o",
"ǭ":"o",
"ø":"o",
"ǿ":"o",
"õ":"o",
"ṍ":"o",
"ṏ":"o",
"ȭ":"o",
"ƣ":"oi",
"ꝏ":"oo",
"ɛ":"e",
"ᶓ":"e",
"ɔ":"o",
"ᶗ":"o",
"ȣ":"ou",
"ṕ":"p",
"ṗ":"p",
"ꝓ":"p",
"ƥ":"p",
"ᵱ":"p",
"ᶈ":"p",
"ꝕ":"p",
"ᵽ":"p",
"ꝑ":"p",
"ꝙ":"q",
"ʠ":"q",
"ɋ":"q",
"ꝗ":"q",
"ŕ":"r",
"ř":"r",
"ŗ":"r",
"ṙ":"r",
"ṛ":"r",
"ṝ":"r",
"ȑ":"r",
"ɾ":"r",
"ᵳ":"r",
"ȓ":"r",
"ṟ":"r",
"ɼ":"r",
"ᵲ":"r",
"ᶉ":"r",
"ɍ":"r",
"ɽ":"r",
"ↄ":"c",
"ꜿ":"c",
"ɘ":"e",
"ɿ":"r",
"ś":"s",
"ṥ":"s",
"š":"s",
"ṧ":"s",
"ş":"s",
"ŝ":"s",
"ș":"s",
"ṡ":"s",
"ṣ":"s",
"ṩ":"s",
"ʂ":"s",
"ᵴ":"s",
"ᶊ":"s",
"ȿ":"s",
"ɡ":"g",
"ᴑ":"o",
"ᴓ":"o",
"ᴝ":"u",
"ť":"t",
"ţ":"t",
"ṱ":"t",
"ț":"t",
"ȶ":"t",
"ẗ":"t",
"ⱦ":"t",
"ṫ":"t",
"ṭ":"t",
"ƭ":"t",
"ṯ":"t",
"ᵵ":"t",
"ƫ":"t",
"ʈ":"t",
"ŧ":"t",
"ᵺ":"th",
"ɐ":"a",
"ᴂ":"ae",
"ǝ":"e",
"ᵷ":"g",
"ɥ":"h",
"ʮ":"h",
"ʯ":"h",
"ᴉ":"i",
"ʞ":"k",
"ꞁ":"l",
"ɯ":"m",
"ɰ":"m",
"ᴔ":"oe",
"ɹ":"r",
"ɻ":"r",
"ɺ":"r",
"ⱹ":"r",
"ʇ":"t",
"ʌ":"v",
"ʍ":"w",
"ʎ":"y",
"ꜩ":"tz",
"ú":"u",
"ŭ":"u",
"ǔ":"u",
"û":"u",
"ṷ":"u",
"ü":"u",
"ǘ":"u",
"ǚ":"u",
"ǜ":"u",
"ǖ":"u",
"ṳ":"u",
"ụ":"u",
"ű":"u",
"ȕ":"u",
"ù":"u",
"ủ":"u",
"ư":"u",
"ứ":"u",
"ự":"u",
"ừ":"u",
"ử":"u",
"ữ":"u",
"ȗ":"u",
"ū":"u",
"ṻ":"u",
"ų":"u",
"ᶙ":"u",
"ů":"u",
"ũ":"u",
"ṹ":"u",
"ṵ":"u",
"ᵫ":"ue",
"ꝸ":"um",
"ⱴ":"v",
"ꝟ":"v",
"ṿ":"v",
"ʋ":"v",
"ᶌ":"v",
"ⱱ":"v",
"ṽ":"v",
"ꝡ":"vy",
"ẃ":"w",
"ŵ":"w",
"ẅ":"w",
"ẇ":"w",
"ẉ":"w",
"ẁ":"w",
"ⱳ":"w",
"ẘ":"w",
"ẍ":"x",
"ẋ":"x",
"ᶍ":"x",
"ý":"y",
"ŷ":"y",
"ÿ":"y",
"ẏ":"y",
"ỵ":"y",
"ỳ":"y",
"ƴ":"y",
"ỷ":"y",
"ỿ":"y",
"ȳ":"y",
"ẙ":"y",
"ɏ":"y",
"ỹ":"y",
"ź":"z",
"ž":"z",
"ẑ":"z",
"ʑ":"z",
"ⱬ":"z",
"ż":"z",
"ẓ":"z",
"ȥ":"z",
"ẕ":"z",
"ᵶ":"z",
"ᶎ":"z",
"ʐ":"z",
"ƶ":"z",
"ɀ":"z",
"ff":"ff",
"ffi":"ffi",
"ffl":"ffl",
"fi":"fi",
"fl":"fl",
"ij":"ij",
"œ":"oe",
"st":"st",
"ₐ":"a",
"ₑ":"e",
"ᵢ":"i",
"ⱼ":"j",
"ₒ":"o",
"ᵣ":"r",
"ᵤ":"u",
"ᵥ":"v",
"ₓ":"x"};
String.prototype.latinise=function(){return this.replace(/[^A-Za-z0-9\[\] ]/g,function(a){return Latinise.latin_map[a]||a})};
String.prototype.latinize=String.prototype.latinise;
String.prototype.isLatin=function(){return this==this.latinise()}

Some examples:

> "Piqué".latinize();
"Pique"
> "Piqué".isLatin();
false
> "Pique".isLatin();
true
> "Piqué".latinise().isLatin();
true

Solution 2 - Javascript

I can't speak to what you are trying to do specifically with the function itself, but if you don't like the regex being built every time, here are two solutions and some caveats about each.

Here is one way to do this:

function makeSortString(s) {
  if(!makeSortString.translate_re) makeSortString.translate_re = /[öäüÖÄÜ]/g;
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  return ( s.replace(makeSortString.translate_re, function(match) { 
    return translate[match]; 
  }) );
}

This will obviously make the regex a property of the function itself. The only thing you may not like about this (or you may, I guess it depends) is that the regex can now be modified outside of the function's body. So, someone could do this to modify the interally-used regex:

makeSortString.translate_re = /[a-z]/g;

So, there is that option.

One way to get a closure, and thus prevent someone from modifying the regex, would be to define this as an anonymous function assignment like this:

var makeSortString = (function() {
  var translate_re = /[öäüÖÄÜ]/g;
  return function(s) {
    var translate = {
      "ä": "a", "ö": "o", "ü": "u",
      "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
    };
    return ( s.replace(translate_re, function(match) { 
      return translate[match]; 
    }) );
  }
})();

Hopefully this is useful to you.


UPDATE: It's early and I don't know why I didn't see the obvious before, but it might also be useful to put you translate object in a closure as well:

var makeSortString = (function() {
  var translate_re = /[öäüÖÄÜ]/g;
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  return function(s) {
    return ( s.replace(translate_re, function(match) { 
      return translate[match]; 
    }) );
  }
})();

Solution 3 - Javascript

The correct terminology for such accents is Diacritics. After Googling this term, I found this function which is part of backbone.paginator. It has a very complete collection of Diacritics and replaces them with their most intuitive ascii character. I found this to be the most complete Javascript solution available today.

The full function for future reference:

function removeDiacritics (str) {

  var defaultDiacriticsRemovalMap = [
    {'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
    {'base':'AA','letters':/[\uA732]/g},
    {'base':'AE','letters':/[\u00C6\u01FC\u01E2]/g},
    {'base':'AO','letters':/[\uA734]/g},
    {'base':'AU','letters':/[\uA736]/g},
    {'base':'AV','letters':/[\uA738\uA73A]/g},
    {'base':'AY','letters':/[\uA73C]/g},
    {'base':'B', 'letters':/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
    {'base':'C', 'letters':/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
    {'base':'D', 'letters':/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
    {'base':'DZ','letters':/[\u01F1\u01C4]/g},
    {'base':'Dz','letters':/[\u01F2\u01C5]/g},
    {'base':'E', 'letters':/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
    {'base':'F', 'letters':/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
    {'base':'G', 'letters':/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
    {'base':'H', 'letters':/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
    {'base':'I', 'letters':/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
    {'base':'J', 'letters':/[\u004A\u24BF\uFF2A\u0134\u0248]/g},
    {'base':'K', 'letters':/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
    {'base':'L', 'letters':/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
    {'base':'LJ','letters':/[\u01C7]/g},
    {'base':'Lj','letters':/[\u01C8]/g},
    {'base':'M', 'letters':/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
    {'base':'N', 'letters':/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
    {'base':'NJ','letters':/[\u01CA]/g},
    {'base':'Nj','letters':/[\u01CB]/g},
    {'base':'O', 'letters':/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
    {'base':'OI','letters':/[\u01A2]/g},
    {'base':'OO','letters':/[\uA74E]/g},
    {'base':'OU','letters':/[\u0222]/g},
    {'base':'P', 'letters':/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
    {'base':'Q', 'letters':/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
    {'base':'R', 'letters':/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
    {'base':'S', 'letters':/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
    {'base':'T', 'letters':/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
    {'base':'TZ','letters':/[\uA728]/g},
    {'base':'U', 'letters':/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
    {'base':'V', 'letters':/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
    {'base':'VY','letters':/[\uA760]/g},
    {'base':'W', 'letters':/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
    {'base':'X', 'letters':/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
    {'base':'Y', 'letters':/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
    {'base':'Z', 'letters':/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},
    {'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},
    {'base':'aa','letters':/[\uA733]/g},
    {'base':'ae','letters':/[\u00E6\u01FD\u01E3]/g},
    {'base':'ao','letters':/[\uA735]/g},
    {'base':'au','letters':/[\uA737]/g},
    {'base':'av','letters':/[\uA739\uA73B]/g},
    {'base':'ay','letters':/[\uA73D]/g},
    {'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},
    {'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},
    {'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},
    {'base':'dz','letters':/[\u01F3\u01C6]/g},
    {'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},
    {'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},
    {'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},
    {'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},
    {'base':'hv','letters':/[\u0195]/g},
    {'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},
    {'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},
    {'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},
    {'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},
    {'base':'lj','letters':/[\u01C9]/g},
    {'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},
    {'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},
    {'base':'nj','letters':/[\u01CC]/g},
    {'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},
    {'base':'oi','letters':/[\u01A3]/g},
    {'base':'ou','letters':/[\u0223]/g},
    {'base':'oo','letters':/[\uA74F]/g},
    {'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},
    {'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},
    {'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},
    {'base':'s','letters':/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},
    {'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},
    {'base':'tz','letters':/[\uA729]/g},
    {'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},
    {'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},
    {'base':'vy','letters':/[\uA761]/g},
    {'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},
    {'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},
    {'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},
    {'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}
  ];

  for(var i=0; i<defaultDiacriticsRemovalMap.length; i++) {
    str = str.replace(defaultDiacriticsRemovalMap[i].letters, defaultDiacriticsRemovalMap[i].base);
  }

  return str;

}

Solution 4 - Javascript

https://stackoverflow.com/a/37511463

> With ES2015/ES6 String.Prototype.Normalize(), > > const str = "Crème Brulée" > str.normalize('NFD').replace(/[\u0300-\u036f]/g, "") > > 'Creme Brulee' > > Two things are happening here: > > 1. normalize()ing to NFD Unicode normal form decomposes combined graphemes into the combination of simple ones. The è of Crème ends up expressed as e + ̀. > 2. Using a regex character class to match the U+0300 → U+036F range, it is now trivial to globally get rid of the diacritics, which the Unicode standard conveniently groups as the Combining Diacritical Marks Unicode block. > > See comment for performance testing. > > Alternatively, if you just want sorting > > Intl.Collator has sufficient support ~85% right now, a polyfill is also available here but I haven't tested it. > > const c = new Intl.Collator(); > ['creme brulee', 'crème brulée', 'crame brulai', 'crome brouillé', > 'creme brulay', 'creme brulfé', 'creme bruléa'].sort(c.compare) > [ 'crame brulai','creme brulay','creme bruléa','creme brulee', > 'crème brulée','creme brulfé','crome brouillé' ] > > > ['creme brulee', 'crème brulée', 'crame brulai', 'crome brouillé'].sort((a,b) => a>b) > ["crame brulai", "creme brulee", "crome brouillé", "crème brulée"]

Solution 5 - Javascript

Simply should be normalized chain and run a replacement codes:

var str = "Letras Á É Í Ó Ú Ñ - á é í ó ú ñ...";
console.log (str.normalize ("NFKD").replace (/[\u0300-\u036F]/g, ""));
// Letras A E I O U N - a e i o u n...

See normalize

Then you can use this function:

function noTilde (s) {
    if (s.normalize != undefined) {
		s = s.normalize ("NFKD");
    }
    return s.replace (/[\u0300-\u036F]/g, "");
}

Solution 6 - Javascript

I think this might work a little cleaner/better (though I haven't test it's performance):

String.prototype.stripAccents = function() {
	var translate_re = /[àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ]/g;
	var translate = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY';
	return (this.replace(translate_re, function(match){
		return translate.substr(translate_re.source.indexOf(match)-1, 1); })
	);
};

Or if you are still too worried about performance, let's get the best of both worlds:

String.prototype.stripAccents = function() {
    var in_chrs =  'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ',
	    out_chrs = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY', 
		transl = {};
    eval('var chars_rgx = /['+in_chrs+']/g');
    for(var i = 0; i < in_chrs.length; i++){ transl[in_chrs.charAt(i)] = out_chrs.charAt(i); }
    return this.replace(chars_rgx, function(match){
        return transl[match]; });
};

EDIT (by @Tomalak)

I appreciate the idea. However, there are several things wrong with the implementation, as outlined in the comment below.

Here is how I would implement it.

var stripAccents = (function () {
  var in_chrs   = 'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ',
      out_chrs  = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY', 
      chars_rgx = new RegExp('[' + in_chrs + ']', 'g'),
      transl    = {}, i,
      lookup    = function (m) { return transl[m] || m; };
      
  for (i=0; i<in_chrs.length; i++) {
    transl[ in_chrs[i] ] = out_chrs[i];
  }

  return function (s) { return s.replace(chars_rgx, lookup); }
})();

Solution 7 - Javascript

Based on the solution by Jason Bunting, here is what I use now.

The whole thing is for the jQuery tablesorter plug-in: For (nearly correct) sorting of non-English tables with tablesorter plugin it is necessary to make use of a custom textExtraction function.

This one:

  • translates the most common accented letters to unaccented ones (the list of supported letters is easily expandable)
  • changes dates in German format ('dd.mm.yyyy') to a recognized format ('yyyy-mm-dd')

Be careful to save the JavaScript file in UTF-8 encoding or it won't work.

// file encoding must be UTF-8!
function getTextExtractor()
{
  return (function() {
    var patternLetters = /[öäüÖÄÜáàâéèêúùûóòôÁÀÂÉÈÊÚÙÛÓÒÔß]/g;
    var patternDateDmy = /^(?:\D+)?(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/;
    var lookupLetters = {
      "ä": "a", "ö": "o", "ü": "u",
      "Ä": "A", "Ö": "O", "Ü": "U",
      "á": "a", "à": "a", "â": "a",
      "é": "e", "è": "e", "ê": "e",
      "ú": "u", "ù": "u", "û": "u",
      "ó": "o", "ò": "o", "ô": "o",
      "Á": "A", "À": "A", "Â": "A",
      "É": "E", "È": "E", "Ê": "E",
      "Ú": "U", "Ù": "U", "Û": "U",
      "Ó": "O", "Ò": "O", "Ô": "O",
      "ß": "s"
    };
    var letterTranslator = function(match) { 
      return lookupLetters[match] || match;
    }

    return function(node) {
      var text = $.trim($(node).text());
      var date = text.match(patternDateDmy);
      if (date)
        return [date[3], date[2], date[1]].join("-");
      else
        return text.replace(patternLetters, letterTranslator);
    }
  })();
}

You can use it like this:

$("table.sortable").tablesorter({ 
  textExtraction: getTextExtractor()
}); 

Solution 8 - Javascript

The complete solution to your request is:

function convert_accented_characters(str){
    var conversions = new Object();
    conversions['ae'] = 'ä|æ|ǽ';
    conversions['oe'] = 'ö|œ';
    conversions['ue'] = 'ü';
    conversions['Ae'] = 'Ä';
    conversions['Ue'] = 'Ü';
    conversions['Oe'] = 'Ö';
    conversions['A'] = 'À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ';
    conversions['a'] = 'à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª';
    conversions['C'] = 'Ç|Ć|Ĉ|Ċ|Č';
    conversions['c'] = 'ç|ć|ĉ|ċ|č';
    conversions['D'] = 'Ð|Ď|Đ';
    conversions['d'] = 'ð|ď|đ';
    conversions['E'] = 'È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě';
    conversions['e'] = 'è|é|ê|ë|ē|ĕ|ė|ę|ě';
    conversions['G'] = 'Ĝ|Ğ|Ġ|Ģ';
    conversions['g'] = 'ĝ|ğ|ġ|ģ';
    conversions['H'] = 'Ĥ|Ħ';
    conversions['h'] = 'ĥ|ħ';
    conversions['I'] = 'Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ';
    conversions['i'] = 'ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı';
    conversions['J'] = 'Ĵ';
    conversions['j'] = 'ĵ';
    conversions['K'] = 'Ķ';
    conversions['k'] = 'ķ';
    conversions['L'] = 'Ĺ|Ļ|Ľ|Ŀ|Ł';
    conversions['l'] = 'ĺ|ļ|ľ|ŀ|ł';
    conversions['N'] = 'Ñ|Ń|Ņ|Ň';
    conversions['n'] = 'ñ|ń|ņ|ň|ʼn';
    conversions['O'] = 'Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ';
    conversions['o'] = 'ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º';
    conversions['R'] = 'Ŕ|Ŗ|Ř';
    conversions['r'] = 'ŕ|ŗ|ř';
    conversions['S'] = 'Ś|Ŝ|Ş|Š';
    conversions['s'] = 'ś|ŝ|ş|š|ſ';
    conversions['T'] = 'Ţ|Ť|Ŧ';
    conversions['t'] = 'ţ|ť|ŧ';
    conversions['U'] = 'Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ';
    conversions['u'] = 'ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ';
    conversions['Y'] = 'Ý|Ÿ|Ŷ';
    conversions['y'] = 'ý|ÿ|ŷ';
    conversions['W'] = 'Ŵ';
    conversions['w'] = 'ŵ';
    conversions['Z'] = 'Ź|Ż|Ž';
    conversions['z'] = 'ź|ż|ž';
    conversions['AE'] = 'Æ|Ǽ';
    conversions['ss'] = 'ß';
    conversions['IJ'] = 'IJ';
    conversions['ij'] = 'ij';
    conversions['OE'] = 'Œ';
    conversions['f'] = 'ƒ';
    for(var i in conversions){
        var re = new RegExp(conversions[i],"g");
        str = str.replace(re,i);
    }
    return str;
}

Solution 9 - Javascript

I can't think about an easier way to efficiently remove all diacritics from a string than using this amazing solution.

See it in action:

var string = "öäüÖÄÜ";

var string_norm = string.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
console.log(string_norm);

Solution 10 - Javascript

If you're looking specifically for a way to convert accented characters to non-accented characters, rather than a way to sort accented characters, with a little finagling, the String.localeCompare function can be manipulated to find the basic latin characters that match the extended ones. For example, you might want to produce a human friendly url slug from a page title. If so, you can do something like this:

var baseChars = [];
for (var i = 97; i < 97 + 26; i++) {
  baseChars.push(String.fromCharCode(i));
}

//if needed, handle fancy compound characters
baseChars = baseChars.concat('ss,aa,ae,ao,au,av,ay,dz,hv,lj,nj,oi,ou,oo,tz,vy'.split(','));

function isUpperCase(c) { return c !== c.toLocaleLowerCase() }

function toBaseChar(c, opts) {
  opts = opts || {};
  //if (!('nonAlphaChar' in opts)) opts.nonAlphaChar = '';
  //if (!('noMatchChar' in opts)) opts.noMatchChar = '';
  if (!('locale' in opts)) opts.locale = 'en';

  var cOpts = {sensitivity: 'base'};

  //exit early for any non-alphabetical character
  if (c.localeCompare('9', opts.locale, cOpts) <= 0) return opts.nonAlphaChar === undefined ? c : opts.nonAlphaChar;

  for (var i = 0; i < baseChars.length; i++) {
    var baseChar = baseChars[i];

    var comp = c.localeCompare(baseChar, opts.locale, cOpts);
    if (comp == 0) return (isUpperCase(c)) ? baseChar.toUpperCase() : baseChar;
  }

  return opts.noMatchChar === undefined ? c : opts.noMatchChar;
}

function latinify(str, opts) {
  return str.replace(/[^\w\s\d]/g, function(c) {
    return toBaseChar(c, opts);
  })
}

// Example:
console.log(latinify('Čeština Tsėhesenėstsestotse Tshivenḓa Emigliàn–Rumagnòl Slovenščina Português Tiếng Việt Straße'))

// "Cestina Tsehesenestsestotse Tshivenda Emiglian–Rumagnol Slovenscina Portugues Tieng Viet Strasse"

This should perform quite well, but if further optimization were needed, a binary search could be used with localeCompare as the comparator to locate the base character. Note that case is preserved, and options allow for either preserving, replacing, or removing characters that aren't alphabetical, or do not have matching latin characters they can be replaced with. This implementation is faster and more flexible, and should work with new characters as they are added. The disadvantage is that compound characters like 'ꝡ' have to be handled specifically, if they need to be supported.

Solution 11 - Javascript

I made a Prototype Version of this:

String.prototype.strip = function() {
  var translate_re = /[öäüÖÄÜß ]/g;
  var translate = {
    "ä":"a", "ö":"o", "ü":"u",
	"Ä":"A", "Ö":"O", "Ü":"U",
	" ":"_", "ß":"ss"   // probably more to come
  };
	return (this.replace(translate_re, function(match){
		return translate[match];})
	);
};

Use like:

var teststring = 'ä ö ü Ä Ö Ü ß';
teststring.strip();

This will will change the String to a_o_u_A_O_U_ss

Solution 12 - Javascript

Basing on existing answers and some suggestions, I've created this one:

String.prototype.removeAccents = function() {

	var removalMap = {
		'A'  : /[AⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄ]/g,
		'AA' : /[Ꜳ]/g,
		'AE' : /[ÆǼǢ]/g,
		'AO' : /[Ꜵ]/g,
		'AU' : /[Ꜷ]/g,
		'AV' : /[ꜸꜺ]/g,
		'AY' : /[Ꜽ]/g,
		'B'  : /[BⒷBḂḄḆɃƂƁ]/g,
		'C'  : /[CⒸCĆĈĊČÇḈƇȻꜾ]/g,
		'D'  : /[DⒹDḊĎḌḐḒḎĐƋƊƉꝹ]/g,
		'DZ' : /[DZDŽ]/g,
		'Dz' : /[DzDž]/g,
		'E'  : /[EⒺEÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ]/g,
		'F'  : /[FⒻFḞƑꝻ]/g,
		'G'  : /[GⒼGǴĜḠĞĠǦĢǤƓꞠꝽꝾ]/g,
		'H'  : /[HⒽHĤḢḦȞḤḨḪĦⱧⱵꞍ]/g,
		'I'  : /[IⒾIÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ]/g,
		'J'  : /[JⒿJĴɈ]/g,
		'K'  : /[KⓀKḰǨḲĶḴƘⱩꝀꝂꝄꞢ]/g,
		'L'  : /[LⓁLĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ]/g,
		'LJ' : /[LJ]/g,
		'Lj' : /[Lj]/g,
		'M'  : /[MⓂMḾṀṂⱮƜ]/g,
		'N'  : /[NⓃNǸŃÑṄŇṆŅṊṈȠƝꞐꞤ]/g,
		'NJ' : /[NJ]/g,
		'Nj' : /[Nj]/g,
		'O'  : /[OⓄOÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ]/g,
		'OI' : /[Ƣ]/g,
		'OO' : /[Ꝏ]/g,
		'OU' : /[Ȣ]/g,
		'P'  : /[PⓅPṔṖƤⱣꝐꝒꝔ]/g,
		'Q'  : /[QⓆQꝖꝘɊ]/g,
		'R'  : /[RⓇRŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ]/g,
		'S'  : /[SⓈSẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ]/g,
		'T'  : /[TⓉTṪŤṬȚŢṰṮŦƬƮȾꞆ]/g,
		'TZ' : /[Ꜩ]/g,
		'U'  : /[UⓊUÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ]/g,
		'V'  : /[VⓋVṼṾƲꝞɅ]/g,
		'VY' : /[Ꝡ]/g,
		'W'  : /[WⓌWẀẂŴẆẄẈⱲ]/g,
		'X'  : /[XⓍXẊẌ]/g,
		'Y'  : /[YⓎYỲÝŶỸȲẎŸỶỴƳɎỾ]/g,
		'Z'  : /[ZⓏZŹẐŻŽẒẔƵȤⱿⱫꝢ]/g,
		'a'  : /[aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ]/g,
		'aa' : /[ꜳ]/g,
		'ae' : /[æǽǣ]/g,
		'ao' : /[ꜵ]/g,
		'au' : /[ꜷ]/g,
		'av' : /[ꜹꜻ]/g,
		'ay' : /[ꜽ]/g,
		'b'  : /[bⓑbḃḅḇƀƃɓ]/g,
		'c'  : /[cⓒcćĉċčçḉƈȼꜿↄ]/g,
		'd'  : /[dⓓdḋďḍḑḓḏđƌɖɗꝺ]/g,
		'dz' : /[dzdž]/g,
		'e'  : /[eⓔeèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ]/g,
		'f'  : /[fⓕfḟƒꝼ]/g,
		'g'  : /[gⓖgǵĝḡğġǧģǥɠꞡᵹꝿ]/g,
		'h'  : /[hⓗhĥḣḧȟḥḩḫẖħⱨⱶɥ]/g,
		'hv' : /[ƕ]/g,
		'i'  : /[iⓘiìíîĩīĭïḯỉǐȉȋịįḭɨı]/g,
		'j'  : /[jⓙjĵǰɉ]/g,
		'k'  : /[kⓚkḱǩḳķḵƙⱪꝁꝃꝅꞣ]/g,
		'l'  : /[lⓛlŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ]/g,
		'lj' : /[lj]/g,
		'm'  : /[mⓜmḿṁṃɱɯ]/g,
		'n'  : /[nⓝnǹńñṅňṇņṋṉƞɲʼnꞑꞥ]/g,
		'nj' : /[nj]/g,
		'o'  : /[oⓞoòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ]/g,
		'oi' : /[ƣ]/g,
		'ou' : /[ȣ]/g,
		'oo' : /[ꝏ]/g,
		'p'  : /[pⓟpṕṗƥᵽꝑꝓꝕ]/g,
		'q'  : /[qⓠqɋꝗꝙ]/g,
		'r'  : /[rⓡrŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ]/g,
		's'  : /[sⓢsßśṥŝṡšṧṣṩșşȿꞩꞅẛ]/g,
		't'  : /[tⓣtṫẗťṭțţṱṯŧƭʈⱦꞇ]/g,
		'tz' : /[ꜩ]/g,
		'u'  : /[uⓤuùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ]/g,
		'v'  : /[vⓥvṽṿʋꝟʌ]/g,
		'vy' : /[ꝡ]/g,
		'w'  : /[wⓦwẁẃŵẇẅẘẉⱳ]/g,
		'x'  : /[xⓧxẋẍ]/g,
		'y'  : /[yⓨyỳýŷỹȳẏÿỷẙỵƴɏỿ]/g,
		'z'  : /[zⓩzźẑżžẓẕƶȥɀⱬꝣ]/g,
	};

	var str = this;

	for(var latin in removalMap) {
	  var nonLatin = removalMap[latin];
	  str = str.replace(nonLatin , latin);
	}

	return str;
}

It uses real chars instead of unicode list and works well.

You can use it like

"ąąą".removeAccents(); // returns "aaa"

You can easily convert this function to not be string prototype. However, as I'm fan of using string prototype in such cases, you'll have to do it yourself.

Solution 13 - Javascript

A direct port to javascript of Kierons solution: https://github.com/rwarasaurus/nano/blob/master/system/helpers.php#L61-73:

/**
 * Normalise a string replacing foreign characters
 *
 * @param {String} str
 * @return {String} str
 */

var normalize = (function () {
    var a = ['À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ'];
    var b = ['A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o'];

    return function (str) {
        var i = a.length;
        while (i--) str = str.replace(a[i], b[i]);
        return str;
    };
}());

And a slightly modified version, using a char-map instead of two arrays:

To compare these two methods I made a simple benchmark: http://jsperf.com/replace-foreign-characters

/**
 * Normalise a string replacing foreign characters
 *
 * @param {String} str
 * @return {String}
 */
var normalize = (function () {
    var map = {
            "À": "A",
            "Á": "A",
            "Â": "A",
            "Ã": "A",
            "Ä": "A",
            "Å": "A",
            "Æ": "AE",
            "Ç": "C",
            "È": "E",
            "É": "E",
            "Ê": "E",
            "Ë": "E",
            "Ì": "I",
            "Í": "I",
            "Î": "I",
            "Ï": "I",
            "Ð": "D",
            "Ñ": "N",
            "Ò": "O",
            "Ó": "O",
            "Ô": "O",
            "Õ": "O",
            "Ö": "O",
            "Ø": "O",
            "Ù": "U",
            "Ú": "U",
            "Û": "U",
            "Ü": "U",
            "Ý": "Y",
            "ß": "s",
            "à": "a",
            "á": "a",
            "â": "a",
            "ã": "a",
            "ä": "a",
            "å": "a",
            "æ": "ae",
            "ç": "c",
            "è": "e",
            "é": "e",
            "ê": "e",
            "ë": "e",
            "ì": "i",
            "í": "i",
            "î": "i",
            "ï": "i",
            "ñ": "n",
            "ò": "o",
            "ó": "o",
            "ô": "o",
            "õ": "o",
            "ö": "o",
            "ø": "o",
            "ù": "u",
            "ú": "u",
            "û": "u",
            "ü": "u",
            "ý": "y",
            "ÿ": "y",
            "Ā": "A",
            "ā": "a",
            "Ă": "A",
            "ă": "a",
            "Ą": "A",
            "ą": "a",
            "Ć": "C",
            "ć": "c",
            "Ĉ": "C",
            "ĉ": "c",
            "Ċ": "C",
            "ċ": "c",
            "Č": "C",
            "č": "c",
            "Ď": "D",
            "ď": "d",
            "Đ": "D",
            "đ": "d",
            "Ē": "E",
            "ē": "e",
            "Ĕ": "E",
            "ĕ": "e",
            "Ė": "E",
            "ė": "e",
            "Ę": "E",
            "ę": "e",
            "Ě": "E",
            "ě": "e",
            "Ĝ": "G",
            "ĝ": "g",
            "Ğ": "G",
            "ğ": "g",
            "Ġ": "G",
            "ġ": "g",
            "Ģ": "G",
            "ģ": "g",
            "Ĥ": "H",
            "ĥ": "h",
            "Ħ": "H",
            "ħ": "h",
            "Ĩ": "I",
            "ĩ": "i",
            "Ī": "I",
            "ī": "i",
            "Ĭ": "I",
            "ĭ": "i",
            "Į": "I",
            "į": "i",
            "İ": "I",
            "ı": "i",
            "IJ": "IJ",
            "ij": "ij",
            "Ĵ": "J",
            "ĵ": "j",
            "Ķ": "K",
            "ķ": "k",
            "Ĺ": "L",
            "ĺ": "l",
            "Ļ": "L",
            "ļ": "l",
            "Ľ": "L",
            "ľ": "l",
            "Ŀ": "L",
            "ŀ": "l",
            "Ł": "l",
            "ł": "l",
            "Ń": "N",
            "ń": "n",
            "Ņ": "N",
            "ņ": "n",
            "Ň": "N",
            "ň": "n",
            "ʼn": "n",
            "Ō": "O",
            "ō": "o",
            "Ŏ": "O",
            "ŏ": "o",
            "Ő": "O",
            "ő": "o",
            "Œ": "OE",
            "œ": "oe",
            "Ŕ": "R",
            "ŕ": "r",
            "Ŗ": "R",
            "ŗ": "r",
            "Ř": "R",
            "ř": "r",
            "Ś": "S",
            "ś": "s",
            "Ŝ": "S",
            "ŝ": "s",
            "Ş": "S",
            "ş": "s",
            "Š": "S",
            "š": "s",
            "Ţ": "T",
            "ţ": "t",
            "Ť": "T",
            "ť": "t",
            "Ŧ": "T",
            "ŧ": "t",
            "Ũ": "U",
            "ũ": "u",
            "Ū": "U",
            "ū": "u",
            "Ŭ": "U",
            "ŭ": "u",
            "Ů": "U",
            "ů": "u",
            "Ű": "U",
            "ű": "u",
            "Ų": "U",
            "ų": "u",
            "Ŵ": "W",
            "ŵ": "w",
            "Ŷ": "Y",
            "ŷ": "y",
            "Ÿ": "Y",
            "Ź": "Z",
            "ź": "z",
            "Ż": "Z",
            "ż": "z",
            "Ž": "Z",
            "ž": "z",
            "ſ": "s",
            "ƒ": "f",
            "Ơ": "O",
            "ơ": "o",
            "Ư": "U",
            "ư": "u",
            "Ǎ": "A",
            "ǎ": "a",
            "Ǐ": "I",
            "ǐ": "i",
            "Ǒ": "O",
            "ǒ": "o",
            "Ǔ": "U",
            "ǔ": "u",
            "Ǖ": "U",
            "ǖ": "u",
            "Ǘ": "U",
            "ǘ": "u",
            "Ǚ": "U",
            "ǚ": "u",
            "Ǜ": "U",
            "ǜ": "u",
            "Ǻ": "A",
            "ǻ": "a",
            "Ǽ": "AE",
            "ǽ": "ae",
            "Ǿ": "O",
            "ǿ": "o"
        },
        nonWord = /\W/g,
        mapping = function (c) {
            return map[c] || c; 
        };
        

    return function (str) {
        return str.replace(nonWord, mapping);
    };
}());

Solution 14 - Javascript

Not a single answer mentions String.localeCompare, which happens to do exactly what you originally wanted, but not what you're asking for.

var list = ['a', 'b', 'c', 'o', 'u', 'z', 'ä', 'ö', 'ü'];

list.sort((a, b) => a.localeCompare(b));

console.log(list);

//Outputs ['a', 'ä', 'b', 'c', 'o', 'ö', 'u', 'ü', 'z']

The second and third parameter are not supported by older browsers though. It's an option worth considering nonetheless.

Solution 15 - Javascript

I just wanted to post my solution using String#localeCompare

const base_chars = [
  '1', '2', '3', '4', '5', '6', '7', '8', '9',
  '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
  'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  '-', '_', ' '
];
const fix = str => str.normalize('NFKD').split('')
    .map(c => base_chars.find(bc => bc.localeCompare(c, 'en', { sensitivity: 'base' })==0))
    .join('');

const str = 'OÒ óëå-123';
console.log(`fix(${str}) = ${fix(str)}`);

Solution 16 - Javascript

Long time ago I did this in Java and found someone else's solution based on a single string that captures part of the Unicode table that was important for the conversion - the rest was converted to ? or any other replacement character. So I tried to convert it to JavaScript. Mind that I'm no JS expert. :-)

TAB_00C0 = "AAAAAAACEEEEIIII" +
	"DNOOOOO*OUUUUYIs" +
	"aaaaaaaceeeeiiii" +
	"?nooooo/ouuuuy?y" +
	"AaAaAaCcCcCcCcDd" +
	"DdEeEeEeEeEeGgGg" +
	"GgGgHhHhIiIiIiIi" +
	"IiJjJjKkkLlLlLlL" +
	"lLlNnNnNnnNnOoOo" +
	"OoOoRrRrRrSsSsSs" +
	"SsTtTtTtUuUuUuUu" +
	"UuUuWwYyYZzZzZzF";

function stripDiacritics(source) {
	var result = source.split('');
	for (var i = 0; i < result.length; i++) {
		var c = source.charCodeAt(i);
		if (c >= 0x00c0 && c <= 0x017f) {
			result[i] = String.fromCharCode(TAB_00C0.charCodeAt(c - 0x00c0));
		} else if (c > 127) {
			result[i] = '?';
		}
	}
	return result.join('');
}

stripDiacritics("Šupa, čo? ľšťčžýæøåℌð")

This converts most of latin1+2 Unicode characters. It is not able to translate single char to multiple. I don't know its performance on JS, in Java this is by far the fastest of common solutions (6-50x), there is no map, there is no regex, nothing. It produces strict ASCII output, potentially with a loss of information, but the size of the output matches the input.

I tested the snippet with http://www.webtoolkitonline.com/javascript-tester.html and it produced Supa, co? lstczyaoa?? as expected.

Solution 17 - Javascript

If you want to achieve sorting where "ä" comes after "a" and is not treated as the same, then you can use a function like mine.

You can always change the alphabet to get different or even weird sortings. However, if you want some letters to be equivalent, then you have to manipulate the strings like a = a.replace(/ä/, 'a') or similar, as many have already replied above. I've included the uppercase letters if someone wants to have all uppercase words before all lowercase words (then you have to ommit .toLowerCase()).

function sortbyalphabet(a,b) {
        alphabet = "0123456789AaÀàÁáÂâÃãÄäBbCcÇçDdÈèÉéÊêËëFfGgHhÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöPpQqRrSsTtÙùÚúÛûÜüVvWwXxÝýŸÿZz";
        a = a.toLowerCase();
        b = b.toLowerCase();
        shorterone = (a.length > b.length ? a : b);
        for (i=0; i<shorterone.length; i++){
            diff = alphabet.indexOf(a.charAt(i)) - alphabet.indexOf(b.charAt(i));
            if (diff!=0){
                return diff;
            }
        }
        // sort the shorter first
        return a.length - b.length;
    }
    var n = ["ast", "Äste", "apfel", "äpfel", "à"];
    console.log(n.sort(sortbyalphabet));
    // should return ["apfel", "ast", "à", "äpfel", "äste"]

Solution 18 - Javascript

A simple and easy way:

function remove-accents(p){
c='áàãâäéèêëíìîïóòõôöúùûüçÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ';s='aaaaaeeeeiiiiooooouuuucAAAAAEEEEIIIIOOOOOUUUUC';n='';for(i=0;i<p.length;i++){if(c.search(p.substr(i,1))>=0){n+=s.substr(c.search(p.substr(i,1)),1);} else{n+=p.substr(i,1);}} return n;
}

So do this:

remove-accents("Thís ís ân accêntéd phráse");

Output:

"This is an accented phrase"

Solution 19 - Javascript

Answer os Crisalin is almost perfect. Just improved the performance to avoid create new RegExp on each run.

var normalizeConversions = [
    { regex: new RegExp('ä|æ|ǽ', 'g'), clean: 'ae' },
    { regex: new RegExp('ö|œ', 'g'), clean: 'oe' },
    { regex: new RegExp('ü', 'g'), clean: 'ue' },
    { regex: new RegExp('Ä', 'g'), clean: 'Ae' },
    { regex: new RegExp('Ü', 'g'), clean: 'Ue' },
    { regex: new RegExp('Ö', 'g'), clean: 'Oe' },
    { regex: new RegExp('À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ', 'g'), clean: 'A' },
    { regex: new RegExp('à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª', 'g'), clean: 'a' },
    { regex: new RegExp('Ç|Ć|Ĉ|Ċ|Č', 'g'), clean: 'C' },
    { regex: new RegExp('ç|ć|ĉ|ċ|č', 'g'), clean: 'c' },
    { regex: new RegExp('Ð|Ď|Đ', 'g'), clean: 'D' },
    { regex: new RegExp('ð|ď|đ', 'g'), clean: 'd' },
    { regex: new RegExp('È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě', 'g'), clean: 'E' },
    { regex: new RegExp('è|é|ê|ë|ē|ĕ|ė|ę|ě', 'g'), clean: 'e' },
    { regex: new RegExp('Ĝ|Ğ|Ġ|Ģ', 'g'), clean: 'G' },
    { regex: new RegExp('ĝ|ğ|ġ|ģ', 'g'), clean: 'g' },
    { regex: new RegExp('Ĥ|Ħ', 'g'), clean: 'H' },
    { regex: new RegExp('ĥ|ħ', 'g'), clean: 'h' },
    { regex: new RegExp('Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ', 'g'), clean: 'I' },
    { regex: new RegExp('ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı', 'g'), clean: 'i' },
    { regex: new RegExp('Ĵ', 'g'), clean: 'J' },
    { regex: new RegExp('ĵ', 'g'), clean: 'j' },
    { regex: new RegExp('Ķ', 'g'), clean: 'K' },
    { regex: new RegExp('ķ', 'g'), clean: 'k' },
    { regex: new RegExp('Ĺ|Ļ|Ľ|Ŀ|Ł', 'g'), clean: 'L' },
    { regex: new RegExp('ĺ|ļ|ľ|ŀ|ł', 'g'), clean: 'l' },
    { regex: new RegExp('Ñ|Ń|Ņ|Ň', 'g'), clean: 'N' },
    { regex: new RegExp('ñ|ń|ņ|ň|ʼn', 'g'), clean: 'n' },
    { regex: new RegExp('Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ', 'g'), clean: 'O' },
    { regex: new RegExp('ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º', 'g'), clean: 'o' },
    { regex: new RegExp('Ŕ|Ŗ|Ř', 'g'), clean: 'R' },
    { regex: new RegExp('ŕ|ŗ|ř', 'g'), clean: 'r' },
    { regex: new RegExp('Ś|Ŝ|Ş|Š', 'g'), clean: 'S' },
    { regex: new RegExp('ś|ŝ|ş|š|ſ', 'g'), clean: 's' },
    { regex: new RegExp('Ţ|Ť|Ŧ', 'g'), clean: 'T' },
    { regex: new RegExp('ţ|ť|ŧ', 'g'), clean: 't' },
    { regex: new RegExp('Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ', 'g'), clean: 'U' },
    { regex: new RegExp('ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ', 'g'), clean: 'u' },
    { regex: new RegExp('Ý|Ÿ|Ŷ', 'g'), clean: 'Y' },
    { regex: new RegExp('ý|ÿ|ŷ', 'g'), clean: 'y' },
    { regex: new RegExp('Ŵ', 'g'), clean: 'W' },
    { regex: new RegExp('ŵ', 'g'), clean: 'w' },
    { regex: new RegExp('Ź|Ż|Ž', 'g'), clean: 'Z' },
    { regex: new RegExp('ź|ż|ž', 'g'), clean: 'z' },
    { regex: new RegExp('Æ|Ǽ', 'g'), clean: 'AE' },
    { regex: new RegExp('ß', 'g'), clean: 'ss' },
    { regex: new RegExp('IJ', 'g'), clean: 'IJ' },
    { regex: new RegExp('ij', 'g'), clean: 'ij' },
    { regex: new RegExp('Œ', 'g'), clean: 'OE' },
    { regex: new RegExp('ƒ', 'g'), clean: 'f' }
];

Usage:

function(str){
    normalizeConversions.forEach(function(normalizeEntry){
        str = str.replace(normalizeEntry.regex, normalizeEntry.clean);
    });
    return str;
};

Solution 20 - Javascript

I've solved it another way, if you like.

Here I used two arrays where searchChars containing which will be replaced and replaceChars containing desired characters.

var text = "your input string";
var searchChars = ['Å','Ä','å','Ö','ö']; // add more charecter.
var replaceChars = ['A','A','a','O','o']; // exact same index to searchChars.
var index;
for (var i = 0; i < text.length; i++) {
  if( $.inArray(text[i], searchChars) >-1 ){ // $.inArray() is from jquery.
    index = searchChars.indexOf(text[i]);
    text = text.slice(0, i) + replaceChars[index] + text.slice(i+1,text.length);
  }
}

Solution 21 - Javascript

For the lads using TypeScript and those who don't want to deal with string prototypes, here is a typescript version of Ed.'s answer:

    // Usage example:
    "Some string".replace(/[^a-zA-Z0-9-_]/g, char => ToLatinMap.get(char) || '')

    // Map:
    export let ToLatinMap: Map<string, string> = new Map<string, string>([
        ["Á", "A"],
        ["Ă", "A"],
        ["Ắ", "A"],
        ["Ặ", "A"],
        ["Ằ", "A"],
        ["Ẳ", "A"],
        ["Ẵ", "A"],
        ["Ǎ", "A"],
        ["Â", "A"],
        ["Ấ", "A"],
        ["Ậ", "A"],
        ["Ầ", "A"],
        ["Ẩ", "A"],
        ["Ẫ", "A"],
        ["Ä", "A"],
        ["Ǟ", "A"],
        ["Ȧ", "A"],
        ["Ǡ", "A"],
        ["Ạ", "A"],
        ["Ȁ", "A"],
        ["À", "A"],
        ["Ả", "A"],
        ["Ȃ", "A"],
        ["Ā", "A"],
        ["Ą", "A"],
        ["Å", "A"],
        ["Ǻ", "A"],
        ["Ḁ", "A"],
        ["Ⱥ", "A"],
        ["Ã", "A"],
        ["Ꜳ", "AA"],
        ["Æ", "AE"],
        ["Ǽ", "AE"],
        ["Ǣ", "AE"],
        ["Ꜵ", "AO"],
        ["Ꜷ", "AU"],
        ["Ꜹ", "AV"],
        ["Ꜻ", "AV"],
        ["Ꜽ", "AY"],
        ["Ḃ", "B"],
        ["Ḅ", "B"],
        ["Ɓ", "B"],
        ["Ḇ", "B"],
        ["Ƀ", "B"],
        ["Ƃ", "B"],
        ["Ć", "C"],
        ["Č", "C"],
        ["Ç", "C"],
        ["Ḉ", "C"],
        ["Ĉ", "C"],
        ["Ċ", "C"],
        ["Ƈ", "C"],
        ["Ȼ", "C"],
        ["Ď", "D"],
        ["Ḑ", "D"],
        ["Ḓ", "D"],
        ["Ḋ", "D"],
        ["Ḍ", "D"],
        ["Ɗ", "D"],
        ["Ḏ", "D"],
        ["Dz", "D"],
        ["Dž", "D"],
        ["Đ", "D"],
        ["Ƌ", "D"],
        ["DZ", "DZ"],
        ["DŽ", "DZ"],
        ["É", "E"],
        ["Ĕ", "E"],
        ["Ě", "E"],
        ["Ȩ", "E"],
        ["Ḝ", "E"],
        ["Ê", "E"],
        ["Ế", "E"],
        ["Ệ", "E"],
        ["Ề", "E"],
        ["Ể", "E"],
        ["Ễ", "E"],
        ["Ḙ", "E"],
        ["Ë", "E"],
        ["Ė", "E"],
        ["Ẹ", "E"],
        ["Ȅ", "E"],
        ["È", "E"],
        ["Ẻ", "E"],
        ["Ȇ", "E"],
        ["Ē", "E"],
        ["Ḗ", "E"],
        ["Ḕ", "E"],
        ["Ę", "E"],
        ["Ɇ", "E"],
        ["Ẽ", "E"],
        ["Ḛ", "E"],
        ["Ꝫ", "ET"],
        ["Ḟ", "F"],
        ["Ƒ", "F"],
        ["Ǵ", "G"],
        ["Ğ", "G"],
        ["Ǧ", "G"],
        ["Ģ", "G"],
        ["Ĝ", "G"],
        ["Ġ", "G"],
        ["Ɠ", "G"],
        ["Ḡ", "G"],
        ["Ǥ", "G"],
        ["Ḫ", "H"],
        ["Ȟ", "H"],
        ["Ḩ", "H"],
        ["Ĥ", "H"],
        ["Ⱨ", "H"],
        ["Ḧ", "H"],
        ["Ḣ", "H"],
        ["Ḥ", "H"],
        ["Ħ", "H"],
        ["Í", "I"],
        ["Ĭ", "I"],
        ["Ǐ", "I"],
        ["Î", "I"],
        ["Ï", "I"],
        ["Ḯ", "I"],
        ["İ", "I"],
        ["Ị", "I"],
        ["Ȉ", "I"],
        ["Ì", "I"],
        ["Ỉ", "I"],
        ["Ȋ", "I"],
        ["Ī", "I"],
        ["Į", "I"],
        ["Ɨ", "I"],
        ["Ĩ", "I"],
        ["Ḭ", "I"],
        ["Ꝺ", "D"],
        ["Ꝼ", "F"],
        ["Ᵹ", "G"],
        ["Ꞃ", "R"],
        ["Ꞅ", "S"],
        ["Ꞇ", "T"],
        ["Ꝭ", "IS"],
        ["Ĵ", "J"],
        ["Ɉ", "J"],
        ["Ḱ", "K"],
        ["Ǩ", "K"],
        ["Ķ", "K"],
        ["Ⱪ", "K"],
        ["Ꝃ", "K"],
        ["Ḳ", "K"],
        ["Ƙ", "K"],
        ["Ḵ", "K"],
        ["Ꝁ", "K"],
        ["Ꝅ", "K"],
        ["Ĺ", "L"],
        ["Ƚ", "L"],
        ["Ľ", "L"],
        ["Ļ", "L"],
        ["Ḽ", "L"],
        ["Ḷ", "L"],
        ["Ḹ", "L"],
        ["Ⱡ", "L"],
        ["Ꝉ", "L"],
        ["Ḻ", "L"],
        ["Ŀ", "L"],
        ["Ɫ", "L"],
        ["Lj", "L"],
        ["Ł", "L"],
        ["LJ", "LJ"],
        ["Ḿ", "M"],
        ["Ṁ", "M"],
        ["Ṃ", "M"],
        ["Ɱ", "M"],
        ["Ń", "N"],
        ["Ň", "N"],
        ["Ņ", "N"],
        ["Ṋ", "N"],
        ["Ṅ", "N"],
        ["Ṇ", "N"],
        ["Ǹ", "N"],
        ["Ɲ", "N"],
        ["Ṉ", "N"],
        ["Ƞ", "N"],
        ["Nj", "N"],
        ["Ñ", "N"],
        ["NJ", "NJ"],
        ["Ó", "O"],
        ["Ŏ", "O"],
        ["Ǒ", "O"],
        ["Ô", "O"],
        ["Ố", "O"],
        ["Ộ", "O"],
        ["Ồ", "O"],
        ["Ổ", "O"],
        ["Ỗ", "O"],
        ["Ö", "O"],
        ["Ȫ", "O"],
        ["Ȯ", "O"],
        ["Ȱ", "O"],
        ["Ọ", "O"],
        ["Ő", "O"],
        ["Ȍ", "O"],
        ["Ò", "O"],
        ["Ỏ", "O"],
        ["Ơ", "O"],
        ["Ớ", "O"],
        ["Ợ", "O"],
        ["Ờ", "O"],
        ["Ở", "O"],
        ["Ỡ", "O"],
        ["Ȏ", "O"],
        ["Ꝋ", "O"],
        ["Ꝍ", "O"],
        ["Ō", "O"],
        ["Ṓ", "O"],
        ["Ṑ", "O"],
        ["Ɵ", "O"],
        ["Ǫ", "O"],
        ["Ǭ", "O"],
        ["Ø", "O"],
        ["Ǿ", "O"],
        ["Õ", "O"],
        ["Ṍ", "O"],
        ["Ṏ", "O"],
        ["Ȭ", "O"],
        ["Ƣ", "OI"],
        ["Ꝏ", "OO"],
        ["Ɛ", "E"],
        ["Ɔ", "O"],
        ["Ȣ", "OU"],
        ["Ṕ", "P"],
        ["Ṗ", "P"],
        ["Ꝓ", "P"],
        ["Ƥ", "P"],
        ["Ꝕ", "P"],
        ["Ᵽ", "P"],
        ["Ꝑ", "P"],
        ["Ꝙ", "Q"],
        ["Ꝗ", "Q"],
        ["Ŕ", "R"],
        ["Ř", "R"],
        ["Ŗ", "R"],
        ["Ṙ", "R"],
        ["Ṛ", "R"],
        ["Ṝ", "R"],
        ["Ȑ", "R"],
        ["Ȓ", "R"],
        ["Ṟ", "R"],
        ["Ɍ", "R"],
        ["Ɽ", "R"],
        ["Ꜿ", "C"],
        ["Ǝ", "E"],
        ["Ś", "S"],
        ["Ṥ", "S"],
        ["Š", "S"],
        ["Ṧ", "S"],
        ["Ş", "S"],
        ["Ŝ", "S"],
        ["Ș", "S"],
        ["Ṡ", "S"],
        ["Ṣ", "S"],
        ["Ṩ", "S"],
        ["Ť", "T"],
        ["Ţ", "T"],
        ["Ṱ", "T"],
        ["Ț", "T"],
        ["Ⱦ", "T"],
        ["Ṫ", "T"],
        ["Ṭ", "T"],
        ["Ƭ", "T"],
        ["Ṯ", "T"],
        ["Ʈ", "T"],
        ["Ŧ", "T"],
        ["Ɐ", "A"],
        ["Ꞁ", "L"],
        ["Ɯ", "M"],
        ["Ʌ", "V"],
        ["Ꜩ", "TZ"],
        ["Ú", "U"],
        ["Ŭ", "U"],
        ["Ǔ", "U"],
        ["Û", "U"],
        ["Ṷ", "U"],
        ["Ü", "U"],
        ["Ǘ", "U"],
        ["Ǚ", "U"],
        ["Ǜ", "U"],
        ["Ǖ", "U"],
        ["Ṳ", "U"],
        ["Ụ", "U"],
        ["Ű", "U"],
        ["Ȕ", "U"],
        ["Ù", "U"],
        ["Ủ", "U"],
        ["Ư", "U"],
        ["Ứ", "U"],
        ["Ự", "U"],
        ["Ừ", "U"],
        ["Ử", "U"],
        ["Ữ", "U"],
        ["Ȗ", "U"],
        ["Ū", "U"],
        ["Ṻ", "U"],
        ["Ų", "U"],
        ["Ů", "U"],
        ["Ũ", "U"],
        ["Ṹ", "U"],
        ["Ṵ", "U"],
        ["Ꝟ", "V"],
        ["Ṿ", "V"],
        ["Ʋ", "V"],
        ["Ṽ", "V"],
        ["Ꝡ", "VY"],
        ["Ẃ", "W"],
        ["Ŵ", "W"],
        ["Ẅ", "W"],
        ["Ẇ", "W"],
        ["Ẉ", "W"],
        ["Ẁ", "W"],
        ["Ⱳ", "W"],
        ["Ẍ", "X"],
        ["Ẋ", "X"],
        ["Ý", "Y"],
        ["Ŷ", "Y"],
        ["Ÿ", "Y"],
        ["Ẏ", "Y"],
        ["Ỵ", "Y"],
        ["Ỳ", "Y"],
        ["Ƴ", "Y"],
        ["Ỷ", "Y"],
        ["Ỿ", "Y"],
        ["Ȳ", "Y"],
        ["Ɏ", "Y"],
        ["Ỹ", "Y"],
        ["Ź", "Z"],
        ["Ž", "Z"],
        ["Ẑ", "Z"],
        ["Ⱬ", "Z"],
        ["Ż", "Z"],
        ["Ẓ", "Z"],
        ["Ȥ", "Z"],
        ["Ẕ", "Z"],
        ["Ƶ", "Z"],
        ["IJ", "IJ"],
        ["Œ", "OE"],
        ["ᴀ", "A"],
        ["ᴁ", "AE"],
        ["ʙ", "B"],
        ["ᴃ", "B"],
        ["ᴄ", "C"],
        ["ᴅ", "D"],
        ["ᴇ", "E"],
        ["ꜰ", "F"],
        ["ɢ", "G"],
        ["ʛ", "G"],
        ["ʜ", "H"],
        ["ɪ", "I"],
        ["ʁ", "R"],
        ["ᴊ", "J"],
        ["ᴋ", "K"],
        ["ʟ", "L"],
        ["ᴌ", "L"],
        ["ᴍ", "M"],
        ["ɴ", "N"],
        ["ᴏ", "O"],
        ["ɶ", "OE"],
        ["ᴐ", "O"],
        ["ᴕ", "OU"],
        ["ᴘ", "P"],
        ["ʀ", "R"],
        ["ᴎ", "N"],
        ["ᴙ", "R"],
        ["ꜱ", "S"],
        ["ᴛ", "T"],
        ["ⱻ", "E"],
        ["ᴚ", "R"],
        ["ᴜ", "U"],
        ["ᴠ", "V"],
        ["ᴡ", "W"],
        ["ʏ", "Y"],
        ["ᴢ", "Z"],
        ["á", "a"],
        ["ă", "a"],
        ["ắ", "a"],
        ["ặ", "a"],
        ["ằ", "a"],
        ["ẳ", "a"],
        ["ẵ", "a"],
        ["ǎ", "a"],
        ["â", "a"],
        ["ấ", "a"],
        ["ậ", "a"],
        ["ầ", "a"],
        ["ẩ", "a"],
        ["ẫ", "a"],
        ["ä", "a"],
        ["ǟ", "a"],
        ["ȧ", "a"],
        ["ǡ", "a"],
        ["ạ", "a"],
        ["ȁ", "a"],
        ["à", "a"],
        ["ả", "a"],
        ["ȃ", "a"],
        ["ā", "a"],
        ["ą", "a"],
        ["ᶏ", "a"],
        ["ẚ", "a"],
        ["å", "a"],
        ["ǻ", "a"],
        ["ḁ", "a"],
        ["ⱥ", "a"],
        ["ã", "a"],
        ["ꜳ", "aa"],
        ["æ", "ae"],
        ["ǽ", "ae"],
        ["ǣ", "ae"],
        ["ꜵ", "ao"],
        ["ꜷ", "au"],
        ["ꜹ", "av"],
        ["ꜻ", "av"],
        ["ꜽ", "ay"],
        ["ḃ", "b"],
        ["ḅ", "b"],
        ["ɓ", "b"],
        ["ḇ", "b"],
        ["ᵬ", "b"],
        ["ᶀ", "b"],
        ["ƀ", "b"],
        ["ƃ", "b"],
        ["ɵ", "o"],
        ["ć", "c"],
        ["č", "c"],
        ["ç", "c"],
        ["ḉ", "c"],
        ["ĉ", "c"],
        ["ɕ", "c"],
        ["ċ", "c"],
        ["ƈ", "c"],
        ["ȼ", "c"],
        ["ď", "d"],
        ["ḑ", "d"],
        ["ḓ", "d"],
        ["ȡ", "d"],
        ["ḋ", "d"],
        ["ḍ", "d"],
        ["ɗ", "d"],
        ["ᶑ", "d"],
        ["ḏ", "d"],
        ["ᵭ", "d"],
        ["ᶁ", "d"],
        ["đ", "d"],
        ["ɖ", "d"],
        ["ƌ", "d"],
        ["ı", "i"],
        ["ȷ", "j"],
        ["ɟ", "j"],
        ["ʄ", "j"],
        ["dz", "dz"],
        ["dž", "dz"],
        ["é", "e"],
        ["ĕ", "e"],
        ["ě", "e"],
        ["ȩ", "e"],
        ["ḝ", "e"],
        ["ê", "e"],
        ["ế", "e"],
        ["ệ", "e"],
        ["ề", "e"],
        ["ể", "e"],
        ["ễ", "e"],
        ["ḙ", "e"],
        ["ë", "e"],
        ["ė", "e"],
        ["ẹ", "e"],
        ["ȅ", "e"],
        ["è", "e"],
        ["ẻ", "e"],
        ["ȇ", "e"],
        ["ē", "e"],
        ["ḗ", "e"],
        ["ḕ", "e"],
        ["ⱸ", "e"],
        ["ę", "e"],
        ["ᶒ", "e"],
        ["ɇ", "e"],
        ["ẽ", "e"],
        ["ḛ", "e"],
        ["ꝫ", "et"],
        ["ḟ", "f"],
        ["ƒ", "f"],
        ["ᵮ", "f"],
        ["ᶂ", "f"],
        ["ǵ", "g"],
        ["ğ", "g"],
        ["ǧ", "g"],
        ["ģ", "g"],
        ["ĝ", "g"],
        ["ġ", "g"],
        ["ɠ", "g"],
        ["ḡ", "g"],
        ["ᶃ", "g"],
        ["ǥ", "g"],
        ["ḫ", "h"],
        ["ȟ", "h"],
        ["ḩ", "h"],
        ["ĥ", "h"],
        ["ⱨ", "h"],
        ["ḧ", "h"],
        ["ḣ", "h"],
        ["ḥ", "h"],
        ["ɦ", "h"],
        ["ẖ", "h"],
        ["ħ", "h"],
        ["ƕ", "hv"],
        ["í", "i"],
        ["ĭ", "i"],
        ["ǐ", "i"],
        ["î", "i"],
        ["ï", "i"],
        ["ḯ", "i"],
        ["ị", "i"],
        ["ȉ", "i"],
        ["ì", "i"],
        ["ỉ", "i"],
        ["ȋ", "i"],
        ["ī", "i"],
        ["į", "i"],
        ["ᶖ", "i"],
        ["ɨ", "i"],
        ["ĩ", "i"],
        ["ḭ", "i"],
        ["ꝺ", "d"],
        ["ꝼ", "f"],
        ["ᵹ", "g"],
        ["ꞃ", "r"],
        ["ꞅ", "s"],
        ["ꞇ", "t"],
        ["ꝭ", "is"],
        ["ǰ", "j"],
        ["ĵ", "j"],
        ["ʝ", "j"],
        ["ɉ", "j"],
        ["ḱ", "k"],
        ["ǩ", "k"],
        ["ķ", "k"],
        ["ⱪ", "k"],
        ["ꝃ", "k"],
        ["ḳ", "k"],
        ["ƙ", "k"],
        ["ḵ", "k"],
        ["ᶄ", "k"],
        ["ꝁ", "k"],
        ["ꝅ", "k"],
        ["ĺ", "l"],
        ["ƚ", "l"],
        ["ɬ", "l"],
        ["ľ", "l"],
        ["ļ", "l"],
        ["ḽ", "l"],
        ["ȴ", "l"],
        ["ḷ", "l"],
        ["ḹ", "l"],
        ["ⱡ", "l"],
        ["ꝉ", "l"],
        ["ḻ", "l"],
        ["ŀ", "l"],
        ["ɫ", "l"],
        ["ᶅ", "l"],
        ["ɭ", "l"],
        ["ł", "l"],
        ["lj", "lj"],
        ["ſ", "s"],
        ["ẜ", "s"],
        ["ẛ", "s"],
        ["ẝ", "s"],
        ["ḿ", "m"],
        ["ṁ", "m"],
        ["ṃ", "m"],
        ["ɱ", "m"],
        ["ᵯ", "m"],
        ["ᶆ", "m"],
        ["ń", "n"],
        ["ň", "n"],
        ["ņ", "n"],
        ["ṋ", "n"],
        ["ȵ", "n"],
        ["ṅ", "n"],
        ["ṇ", "n"],
        ["ǹ", "n"],
        ["ɲ", "n"],
        ["ṉ", "n"],
        ["ƞ", "n"],
        ["ᵰ", "n"],
        ["ᶇ", "n"],
        ["ɳ", "n"],
        ["ñ", "n"],
        ["nj", "nj"],
        ["ó", "o"],
        ["ŏ", "o"],
        ["ǒ", "o"],
        ["ô", "o"],
        ["ố", "o"],
        ["ộ", "o"],
        ["ồ", "o"],
        ["ổ", "o"],
        ["ỗ", "o"],
        ["ö", "o"],
        ["ȫ", "o"],
        ["ȯ", "o"],
        ["ȱ", "o"],
        ["ọ", "o"],
        ["ő", "o"],
        ["ȍ", "o"],
        ["ò", "o"],
        ["ỏ", "o"],
        ["ơ", "o"],
        ["ớ", "o"],
        ["ợ", "o"],
        ["ờ", "o"],
        ["ở", "o"],
        ["ỡ", "o"],
        ["ȏ", "o"],
        ["ꝋ", "o"],
        ["ꝍ", "o"],
        ["ⱺ", "o"],
        ["ō", "o"],
        ["ṓ", "o"],
        ["ṑ", "o"],
        ["ǫ", "o"],
        ["ǭ", "o"],
        ["ø", "o"],
        ["ǿ", "o"],
        ["õ", "o"],
        ["ṍ", "o"],
        ["ṏ", "o"],
        ["ȭ", "o"],
        ["ƣ", "oi"],
        ["ꝏ", "oo"],
        ["ɛ", "e"],
        ["ᶓ", "e"],
        ["ɔ", "o"],
        ["ᶗ", "o"],
        ["ȣ", "ou"],
        ["ṕ", "p"],
        ["ṗ", "p"],
        ["ꝓ", "p"],
        ["ƥ", "p"],
        ["ᵱ", "p"],
        ["ᶈ", "p"],
        ["ꝕ", "p"],
        ["ᵽ", "p"],
        ["ꝑ", "p"],
        ["ꝙ", "q"],
        ["ʠ", "q"],
        ["ɋ", "q"],
        ["ꝗ", "q"],
        ["ŕ", "r"],
        ["ř", "r"],
        ["ŗ", "r"],
        ["ṙ", "r"],
        ["ṛ", "r"],
        ["ṝ", "r"],
        ["ȑ", "r"],
        ["ɾ", "r"],
        ["ᵳ", "r"],
        ["ȓ", "r"],
        ["ṟ", "r"],
        ["ɼ", "r"],
        ["ᵲ", "r"],
        ["ᶉ", "r"],
        ["ɍ", "r"],
        ["ɽ", "r"],
        ["ↄ", "c"],
        ["ꜿ", "c"],
        ["ɘ", "e"],
        ["ɿ", "r"],
        ["ś", "s"],
        ["ṥ", "s"],
        ["š", "s"],
        ["ṧ", "s"],
        ["ş", "s"],
        ["ŝ", "s"],
        ["ș", "s"],
        ["ṡ", "s"],
        ["ṣ", "s"],
        ["ṩ", "s"],
        ["ʂ", "s"],
        ["ᵴ", "s"],
        ["ᶊ", "s"],
        ["ȿ", "s"],
        ["ɡ", "g"],
        ["ᴑ", "o"],
        ["ᴓ", "o"],
        ["ᴝ", "u"],
        ["ť", "t"],
        ["ţ", "t"],
        ["ṱ", "t"],
        ["ț", "t"],
        ["ȶ", "t"],
        ["ẗ", "t"],
        ["ⱦ", "t"],
        ["ṫ", "t"],
        ["ṭ", "t"],
        ["ƭ", "t"],
        ["ṯ", "t"],
        ["ᵵ", "t"],
        ["ƫ", "t"],
        ["ʈ", "t"],
        ["ŧ", "t"],
        ["ᵺ", "th"],
        ["ɐ", "a"],
        ["ᴂ", "ae"],
        ["ǝ", "e"],
        ["ᵷ", "g"],
        ["ɥ", "h"],
        ["ʮ", "h"],
        ["ʯ", "h"],
        ["ᴉ", "i"],
        ["ʞ", "k"],
        ["ꞁ", "l"],
        ["ɯ", "m"],
        ["ɰ", "m"],
        ["ᴔ", "oe"],
        ["ɹ", "r"],
        ["ɻ", "r"],
        ["ɺ", "r"],
        ["ⱹ", "r"],
        ["ʇ", "t"],
        ["ʌ", "v"],
        ["ʍ", "w"],
        ["ʎ", "y"],
        ["ꜩ", "tz"],
        ["ú", "u"],
        ["ŭ", "u"],
        ["ǔ", "u"],
        ["û", "u"],
        ["ṷ", "u"],
        ["ü", "u"],
        ["ǘ", "u"],
        ["ǚ", "u"],
        ["ǜ", "u"],
        ["ǖ", "u"],
        ["ṳ", "u"],
        ["ụ", "u"],
        ["ű", "u"],
        ["ȕ", "u"],
        ["ù", "u"],
        ["ủ", "u"],
        ["ư", "u"],
        ["ứ", "u"],
        ["ự", "u"],
        ["ừ", "u"],
        ["ử", "u"],
        ["ữ", "u"],
        ["ȗ", "u"],
        ["ū", "u"],
        ["ṻ", "u"],
        ["ų", "u"],
        ["ᶙ", "u"],
        ["ů", "u"],
        ["ũ", "u"],
        ["ṹ", "u"],
        ["ṵ", "u"],
        ["ᵫ", "ue"],
        ["ꝸ", "um"],
        ["ⱴ", "v"],
        ["ꝟ", "v"],
        ["ṿ", "v"],
        ["ʋ", "v"],
        ["ᶌ", "v"],
        ["ⱱ", "v"],
        ["ṽ", "v"],
        ["ꝡ", "vy"],
        ["ẃ", "w"],
        ["ŵ", "w"],
        ["ẅ", "w"],
        ["ẇ", "w"],
        ["ẉ", "w"],
        ["ẁ", "w"],
        ["ⱳ", "w"],
        ["ẘ", "w"],
        ["ẍ", "x"],
        ["ẋ", "x"],
        ["ᶍ", "x"],
        ["ý", "y"],
        ["ŷ", "y"],
        ["ÿ", "y"],
        ["ẏ", "y"],
        ["ỵ", "y"],
        ["ỳ", "y"],
        ["ƴ", "y"],
        ["ỷ", "y"],
        ["ỿ", "y"],
        ["ȳ", "y"],
        ["ẙ", "y"],
        ["ɏ", "y"],
        ["ỹ", "y"],
        ["ź", "z"],
        ["ž", "z"],
        ["ẑ", "z"],
        ["ʑ", "z"],
        ["ⱬ", "z"],
        ["ż", "z"],
        ["ẓ", "z"],
        ["ȥ", "z"],
        ["ẕ", "z"],
        ["ᵶ", "z"],
        ["ᶎ", "z"],
        ["ʐ", "z"],
        ["ƶ", "z"],
        ["ɀ", "z"],
        ["ff", "ff"],
        ["ffi", "ffi"],
        ["ffl", "ffl"],
        ["fi", "fi"],
        ["fl", "fl"],
        ["ij", "ij"],
        ["œ", "oe"],
        ["st", "st"],
        ["ₐ", "a"],
        ["ₑ", "e"],
        ["ᵢ", "i"],
        ["ⱼ", "j"],
        ["ₒ", "o"],
        ["ᵣ", "r"],
        ["ᵤ", "u"],
        ["ᵥ", "v"],
        ["ₓ", "x"],
    ]);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomalakView Question on Stackoverflow
Solution 1 - JavascriptEd.View Answer on Stackoverflow
Solution 2 - JavascriptJason BuntingView Answer on Stackoverflow
Solution 3 - JavascriptJeroen OomsView Answer on Stackoverflow
Solution 4 - JavascriptRevadikeView Answer on Stackoverflow
Solution 5 - JavascriptatiruzView Answer on Stackoverflow
Solution 6 - JavascriptMartin_LakesView Answer on Stackoverflow
Solution 7 - JavascriptTomalakView Answer on Stackoverflow
Solution 8 - JavascriptCrisalin PetrovschiView Answer on Stackoverflow
Solution 9 - JavascriptTakit IsyView Answer on Stackoverflow
Solution 10 - JavascriptundefinedView Answer on Stackoverflow
Solution 11 - JavascriptJan HaggeView Answer on Stackoverflow
Solution 12 - JavascriptAdam PietrasiakView Answer on Stackoverflow
Solution 13 - JavascriptyckartView Answer on Stackoverflow
Solution 14 - JavascriptPrinzhornView Answer on Stackoverflow
Solution 15 - JavascriptdinigoView Answer on Stackoverflow
Solution 16 - Javascriptvirgo47View Answer on Stackoverflow
Solution 17 - JavascriptjakovView Answer on Stackoverflow
Solution 18 - JavascriptKelvin MarquesView Answer on Stackoverflow
Solution 19 - JavascriptrmptView Answer on Stackoverflow
Solution 20 - JavascriptSamiulView Answer on Stackoverflow
Solution 21 - JavascripteddyP23View Answer on Stackoverflow