Let's make a solution in Spanish with regular expressions.
About the letters of Spanish:
For regular expressions in JavaScript, the ñ
and the accents are not word characters 1 .
1 : Not included in \w
, and therefore \b
misses them
In JavaScript 2 , we have to match the previous character (or the beginning of the string) and include it in the replacement, followed by a lowercase letter.
2 : Because in JavaScript there are no backward inspections ( lookbehinds ), as there are in other dialects of regex.
To capitalize the lowercase at the beginning of each word:
const re = /(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])([a-záéíóúüñ])/g;
texto.replace(re, function(match, caracterPrevio, minuscula) {
return caracterPrevio + minuscula.toLocaleUpperCase(['es', 'gl', 'ca', 'pt', 'en']);
});
And, in addition, we can take to lowercase all the rest, doing:
- that also matches initial capitals (not to replace),
- and with intermediate capital letters (to lower case).
Solution:
function titleCase(texto) {
const re = /(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])(?:([a-záéíóúüñ])|([A-ZÁÉÍÓÚÜÑ]))|([A-ZÁÉÍÓÚÜÑ]+)/gu;
return texto.replace(re,
(m, caracterPrevio, minuscInicial, mayuscInicial, mayuscIntermedias) => {
const locale = ['es', 'gl', 'ca', 'pt', 'en'];
if (mayuscIntermedias)
return mayuscIntermedias.toLocaleLowerCase(locale);
return caracterPrevio
+ (minuscInicial ? minuscInicial.toLocaleUpperCase(locale) : mayuscInicial);
}
);
}
Description:
/(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])(?:([a-záéíóúüñ])|([A-ZÁÉÍÓÚÜÑ]))|([A-ZÁÉÍÓÚÜÑ]+)/gu
They are 2 alternatives in a OR : /1|2/gu
(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])(?:([a-záéíóúüñ])|([A-ZÁÉÍÓÚÜÑ]))
- INITIAL LETTER.
-
(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])
- Start of the text or any character that is not alphabetic.
It is the first group = > the callback is passed in the variable caracterPrevio
.
-
(?:([a-záéíóúüñ])|([A-ZÁÉÍÓÚÜÑ]))
- The first letter of the word, either:
([a-záéíóúüñ])
- lowercase letter = > is passed as variable minuscInicial
, or% ([A-ZÁÉÍÓÚÜÑ])
- uppercase letter = > is passed as variable mayuscInicial
.
([A-ZÁÉÍÓÚÜÑ]+)
- INTERMEDIATE CAPITAL LETTERS
When it coincides with this part, it means that it did not coincide with the first one. Therefore, we know that it is not a letter at the beginning of a word, but an intermediate letter.
-
[A-ZÁÉÍÓÚÜÑ]+
matches 1 or more uppercase letters (not initials), so we can lower them to lowercase.
It is the fourth group = > is passed as variable mayuscIntermedias
.
Demo:
//Leva a mayúsculas la primera letra de cada palabra
function titleCase(texto) {
const re = /(^|[^A-Za-zÁÉÍÓÚÜÑáéíóúüñ])(?:([a-záéíóúüñ])|([A-ZÁÉÍÓÚÜÑ]))|([A-ZÁÉÍÓÚÜÑ]+)/gu;
return texto.replace(re,
(m, caracterPrevio, minuscInicial, mayuscInicial, mayuscIntermedias) => {
const locale = ['es', 'gl', 'ca', 'pt', 'en'];
//Son letras mayúsculas en el medio de la palabra
// => llevar a minúsculas.
if (mayuscIntermedias)
return mayuscIntermedias.toLocaleLowerCase(locale);
//Es la letra inicial de la palabra
// => dejar el caracter previo como está.
// => si la primera letra es minúscula, capitalizar
// sino, dejar como está.
return caracterPrevio
+ (minuscInicial ? minuscInicial.toLocaleUpperCase(locale) : mayuscInicial);
}
);
}
//Evento para mostrar el resultado cada vez que se ingresa un caracter
document.getElementById('ingreso')
.addEventListener('input',
event => {
document.getElementById('resultado')
.innerText = titleCase(event.target.value);
}
);
<input type="text"
id="ingreso"
placeholder="Escribí texto para llevar a mayúsculas la primera letra de cada palabra"
style="width:100%">
<pre id="resultado">