3

For example if a word is "Users" and the replacement is "utilisateurs", is there some kind of function that will allow me to conver the replacement string to the same level of capitals/non-capitals as the original word?

This is a final part of a major language translation using jquery, textnodes, exact and partial string matching.

Now I just want to make sure as the final and professional touch, is to make sure the case of the translated/replaced words, match the case of the original words/phrases.

I am not sure how I can apply this as a replace call.

I want this to be as a function

function CopyCase(original,new) {

    // copy the case of the original to the new
}

Only not sure how to do that.

crosenblum
  • 1,869
  • 5
  • 34
  • 57
  • this thread doesn't answer the question, but may give some useful info nonetheless http://stackoverflow.com/questions/2332811/capitalize-words-in-string – Brandon Frohbieter Mar 01 '11 at 18:27
  • I need this as a function, 2 parameters, original, new, and then how to make the new word has the same case as the first one. – crosenblum Mar 01 '11 at 18:29
  • so you want `Users` to translate to `Utilisateurs` ... would you want `UseRs` to translate to `UtiLisateurs` or to something else? How would you want to handle `USERS`? Uppercase the whole translated string? – Sean Vieira Mar 01 '11 at 18:52
  • I just want to match the case of the original word. If it's all caps, the replacement should be all caps, if it's all lower case, then all lower case. – crosenblum Mar 01 '11 at 19:26

3 Answers3

1

Here's a function that will handle cases without internal capitalization:

function caseWord(word, upper) {
    return String.prototype[ upper ? "toUpperCase" : "toLowerCase"].apply(word[0]) + word.slice(1);
}
function caseReplace(s, fromWord, toWord) {
    return s.replace(caseWord(fromWord), caseWord(toWord))
            .replace(caseWord(fromWord, true), caseWord(toWord, true));
}

console.log(caseReplace("The users have joined the Users union.", "users", "utilisateurs"))
console.log(caseReplace("The lovers have joined the Lovers union.", "lovers", "amants"))

// The utilisateurs have joined the Utilisateurs union.
// The amants have joined the Amants union.
harpo
  • 41,820
  • 13
  • 96
  • 131
  • Can this be converted to a function? – crosenblum Mar 01 '11 at 18:29
  • The problem being is that I have a long list of phrases and words, with capitlization different for each. So I have no way of knowing ahead of time which character is going to be caps/not caps ahead of time. – crosenblum Mar 01 '11 at 18:36
  • This isn't the signature you specified (while I was writing it), but may be useful. – harpo Mar 01 '11 at 18:47
0

The String.replace method accepts a callback function as its second argument. In that callback, you can perform any special processing you need, before returning a replacement string.

var translations = {
    users: "utilisateurs",
    apples: "pommes",
    ...
};

// You could generate the regular expression from the object above
// or if the number of words is high, not use regular expressions at all.
s = s.replace(/users|apples|oranges/gi, function (match) {
    return matchCase(translations[match], match);
});

function getCase(ch) {
    return ch == ch.toUpperCase()
        ? "Upper"
        : "Lower";
}

function convertCase(s, case) {
    return s["to" + case + "Case"]();
}

function matchCase(s, target) {
    return convertCase(s[0], getCase(target[0]))
        + convertCase(s.substr(1), getCase(target[1]));
}
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • Will this apply to multiple words or just 1 word at a time? – crosenblum Mar 01 '11 at 18:37
  • Multiple words. But as I said, if you have too many words, using regular expressions is an overkill. I would split the string into an array of words, walk over the array and do translation/case matching of items, and then join the array back into a string. – Ates Goral Mar 01 '11 at 18:53
0
function matchCase (word1, word2) {
  //   1) Words starting with two capital letters are assumed to be all caps.
  //   2) Words starting with two lower case letters are assumed to be all lower case.
  //   3) Words starting with an upper case followed by a lowercase letter are
  //      all lower case except the first letter.

   return word1[0] === word1[0].toLowerCase () ? word2.toLowerCase () :
          word1[1] === word1[1].toLowerCase () ? word2[0].toUpperCase () + word2.slice (1).toLowerCase () :
            word2.toUpperCase ();  
}

matchCase ('Word', 'mot')
"Mot"
matchCase ('WOrd', 'mot')
"MOT"
matchCase ('word', 'mot')
"mot"
matchCase ('wOrD', 'mot')
"mot"
matchCase ('woRD', 'mot')
"mot"

Edited to change the test for lower case which should now be language agnostic (if the underlying toLowerCase function is)

HBP
  • 15,685
  • 6
  • 28
  • 34
  • ES6 Version which also works if there's no 2nd character: function matchCaseSimple(word1, word2) { // 1) Words starting with two capital letters are assumed to be all caps. // 2) Words starting with two lower case letters are assumed to be all lower case. // 3) Words starting with an upper case followed by a lowercase letter are // all lower case except the first letter. return word1[0] === word1[0].toLowerCase() ? word2.toLowerCase() : word1[1] === word1[1]?.toLowerCase() ?? '' ? word2[0].toUpperCase() + word2.slice(1)?.toLowerCase() : word2.toUpperCase() } – Aerodynamic Jan 10 '22 at 14:15