将Unicode字符串转换为“大写首字母”Javascript

5

我有一个JavaScript大小写转换问题,由于涉及到非英文字母,我无法解决。我的主要问题是土耳其字母表。

我需要做的是:

  • hello world => Hello World
  • HELLO WORLD => Hello World
  • hELLO wOrLd => Hello World

这是我目前已经完成的内容:

String.prototype.turkishToUpper = function(){
    var stringlow = this;
    var letterslow = { 'i': 'İ', 'ş': 'Ş', 'ğ': 'Ğ', 'ü': 'Ü', 'ö': 'Ö', 'ç': 'Ç', 'ı': 'I' };
    stringlow = stringlow.replace(/(([iışğüçö]))/g, function(letterlow){ return letterslow[letterlow]; })
    return stringlow.toUpperCase();
}

String.prototype.turkishToLower = function(){
    var stringup = this;
    var lettersup = { 'İ': 'i', 'I': 'ı', 'Ş': 'ş', 'Ğ': 'ğ', 'Ü': 'ü', 'Ö': 'ö', 'Ç': 'ç' };
    stringup = stringup.replace(/(([İIŞĞÜÇÖ]))/g, function(letterup){ return lettersup[letterup]; })
    return stringup.toLowerCase();
}

String.prototype.toProperCase = function () {
    return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).turkishToUpper() + txt.substr(1).turkishToLower();});
};

但这并没有给我正确的结果,我怀疑正则表达式替换不能在Unicode上使用,只能在ASCII上使用。
当我测试土耳其字符时,得到了错误的结果。
- şeker 变成了 şEker 而不是 Şeker - çoban ırmak 变成了 çOban ıRmak 而不是 Çoban Irmak
此外,如果这个问题可以解决,我需要一个锦上添花的功能,不仅可以通过空格分隔单词,还可以通过其他停止字符(如:- = /等)分隔单词。
- hello-world 变成 Hello-World - hello:world 变成 Hello:World
我已经阅读了许多类似的问题,但迄今为止没有运气。
谢谢!
注:我认为这被称为标题大小写,但有些人认为它是帕斯卡尔大小写。坦白说,我对解决Unicode问题(我相信这是根本原因)更感兴趣,而不是语义,所以如果我使用了错误的术语,请原谅我 :)

1
为什么不使用CSS来实现这个?http://jsfiddle.net/3jg3b/ - text-transform: capitalize - Andreas
你的正则表达式选择器有问题。\S 表示非空字符,但 JavaScript 将 ş、ç 识别为空格。请参考 http://blog.stevenlevithan.com/archives/javascript-regex-and-unicode。 - hkutluay
我没有使用CSS @Andreas,因为这是用于纠正用户输入格式错误的。 - Serkan Durusoy
是的,@hkutluay,我知道这一点,因此在主题上给出了Unicode提示 ;) - Serkan Durusoy
它只能与土耳其语一起使用,还是也可以与其他语言一起使用? - hippietrail
嗨@hippietrail,在我的情况下,土耳其语很好,但实际上下面的解决方案似乎可以处理大多数(如果不是全部)带重音符号的字符。唯一的主要问题是土耳其语中的“i”,这是一个重大的非标准问题。 - Serkan Durusoy
4个回答

8

独立函数:

function toProperCase(s){
    return s.replace(/([^\s:\-])([^\s:\-]*)/g,function($0,$1,$2){
        return $1.toUpperCase()+$2.toLowerCase();
    });
}

或者用于扩展String.prototype:

String.prototype.toProperCase=function() {
    return this.replace(/([^\s:\-])([^\s:\-]*)/g,function($0,$1,$2){
        return $1.toUpperCase()+$2.toLowerCase();
    });
}

"çoban ırmak becomes çOban ıRmak intead of Çoban Irmak Hello-wOrld".toProperCase();
// "Çoban Irmak Becomes Çoban Irmak Intead Of Çoban Irmak Hello-World"

更新:

下面的代码使用自定义功能来转换本地特定字符(部分测试过)。代码将函数添加到 String.prototype 中:toLocaleProperCase2toLocaleLowerCase2toLocaleUpperCase2

(function(){
    // locale specific chars
    // IMPORTANT: name of locale must be always in lower case (for "tr-TR" locale - "tr-tr") !!!
    var localeInfos={
            "tr-tr": { lower: { i:"İ", ı:"I", ş:"Ş", ğ:"Ğ", ü:"Ü", ç:"Ç", ö:"Ö" },
                       upper: { İ:"i", I:"ı", Ş:"ş", Ğ:"ğ", Ü:"ü", Ç:"ç", Ö:"ö" } }
        },
        localeInfo;
    // helper vars
    var mask="\\s:\\-", // add additional delimeters chars to the mask if needed
        rg=new RegExp("([^"+mask+"])([^"+mask+"]*)","g");
    var fnToLocaleLower=function(s){ return localeInfo.upper[s]; },
        fnToLocaleUpper=function(s){ return localeInfo.lower[s]; },
        fnToProper=function($0,$1,$2){
            if(localeInfo){
                if(localeInfo.lower.hasOwnProperty($1))$1=localeInfo.lower[$1];
                $2=$2.replace(localeInfo.upperSearchRegExp,fnToLocaleLower);
            }
            return $1.toUpperCase()+$2.toLowerCase();
        };
    // helper calculations
    var localeInfosKeys=Object.keys(localeInfos);
    for(var i=0;localeInfo=localeInfos[localeInfosKeys[i]];i++){
        localeInfo.lowerSearchRegExp=new RegExp("["+Object.keys(localeInfo.lower).join("")+"]","g");
        localeInfo.upperSearchRegExp=new RegExp("["+Object.keys(localeInfo.upper).join("")+"]","g");
    }

    // extending String.prototype
    String.prototype.toLocaleProperCase2=function toLocaleProperCase2(locale){
        localeInfo=localeInfos[arguments.length?locale.toLowerCase():null];
        return this.replace(rg,fnToProper);
    };
    String.prototype.toLocaleLowerCase2=function toLocaleLowerCase2(locale){
        return ((localeInfo=localeInfos[arguments.length?locale.toLowerCase():null]) ?
                this.replace(localeInfo.upperSearchRegExp,fnToLocaleLower):
                this).toLowerCase();
    };
    String.prototype.toLocaleUpperCase2=function toLocaleUpperCase2(locale){
        return ((localeInfo=localeInfos[arguments.length?locale.toLowerCase():null]) ?
                this.replace(localeInfo.lowerSearchRegExp,fnToLocaleUpper) :
                this).toUpperCase();
    };
})();

// testing
var sss="çoban ırmak ibecıoimes çOban ıRmak intead of Çoban IrImaİk Hello-wOrld";
console.log("Origin:    ", sss);
console.log("Proper TR: ", sss.toLocaleProperCase2("tr-TR"));
console.log("Proper:    ", sss.toLocaleProperCase2());
console.log("Lower TR:  ", sss.toLocaleLowerCase2("tr-TR"));
console.log("Lower:     ", sss.toLocaleLowerCase2());
console.log("Upper TR:  ", sss.toLocaleUpperCase2("tr-TR"));
console.log("Upper:     ", sss.toLocaleUpperCase2());

// Origin:    çoban ırmak ibecıoimes çOban ıRmak intead of Çoban IrImaİk Hello-wOrld
// Proper TR: Çoban Irmak İbecıoimes Çoban Irmak İntead Of Çoban Irımaik Hello-World
// Proper:    Çoban Irmak Ibecıoimes Çoban Irmak Intead Of Çoban Irimaik Hello-World
// Lower TR:  çoban ırmak ibecıoimes çoban ırmak intead of çoban ırımaik hello-world
// Lower:     çoban ırmak ibecıoimes çoban ırmak intead of çoban irimaik hello-world
// Upper TR:  ÇOBAN IRMAK İBECIOİMES ÇOBAN IRMAK İNTEAD OF ÇOBAN IRIMAİK HELLO-WORLD
// Upper:     ÇOBAN IRMAK IBECIOIMES ÇOBAN IRMAK INTEAD OF ÇOBAN IRIMAİK HELLO-WORLD

谢谢@andrew-d,这几乎是完美的,唯一的问题是土耳其字母“i”非常不标准。大写的“i”是“İ”,小写的“I”是“ı”。我该如何在方程式中引入这个? - Serkan Durusoy
@andrew:你是说这段代码可以将“ırmak”转换为“Irmak”吗? @Serkan:你是说它不能,但还是接受了它吗?(我很困惑。) - hippietrail
这个回答比第一个回答好多了,不过我已经接受了第一个回答,因为它已经99%完美 :) 而且这最后一次更新似乎解决了所有问题,非常感谢! - Serkan Durusoy
感谢这些有用的提示。Adamsın adam。 - Sedat Kumcu

0
这是一个可以完成任务的JS函数。
function toProperCase(string) {   
    output = '';
    explodedString = string.split(' '); //explode string by space
    for(var i=0;i<explodedString.length;i++){
        output += explodedString[i].charAt(0).toUpperCase() + explodedString[i].slice(1).toLowerCase()+' ';
    }
    return output.slice(0, -1);
}

1
不要在数组中使用 for (... in ...)JavaScript “For …in” with Arrays - Andreas

0
String.prototype.toProperCase = function (){
   var arr= this.toLowerCase().split(' ');
   for( var i=0;i<arr.length;i++){
      arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1);
   };
   return arr.join(' ');
};

'çoban ırmak'.toProperCase() // "Çoban Irmak"

0

另一个选择,但是锦上添花的一点:

function toProperCase( str ) {

    var i,
        j,
        chars,
        arr;

    arr = str.toLowerCase( ).split("");

    chars = {
        " " : true,
        "-" : true,
        ":" : true,
        "=" : true,
        "/" : true
    };

    for( var i = 0, j = -1; i < arr.length; i += 1, j += 1 ) {
        // if previous char (j) exists in chars and current (i) does not;
        // replace with uppercase equivalent.
        if ( ( arr[j] && chars[ arr[j] ] && !chars[ arr[i] ] ) || i === 0){
            arr[i] = arr[i].toUpperCase( );
        }
    }

    return arr.join("");
}

希望这能有所帮助 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接