Tillito
Tillito

Reputation: 7868

Replace straight quotation marks with typographic ones: "My text" to „My text“

I want to change "My text" to „My text“ everywhere automatically, because this is the correct way this is written in German. The quotation marks can be anywhere in the text.

Is there an easy way to achieve this?

The solution should check the very first character, the very last, something like "this", or (check "this") ...

My current approach is:

public static string FixGermanQuotationMarks(string input)
{
    string output = input;
    if (output[0] == '"') output = "„" + output.Substring(1, output.Length - 1);

    if (output.EndsWith("\"")) output = output.Substring(0, output.Length-1) + '“';

    output = output
        .Replace(" \"", " „")
        .Replace("(\"", "(„")
        .Replace("<\"", "<„")

        .Replace("\".", "“.")
        .Replace("\")", "“)")
        .Replace("\"<", "“<")
        .Replace("\" ", "“ ");

    return output;
}

but this is not elegant at all.

EDIT:

I was asked for example input and output. Here you go:

"Chili Pasilla" ist mein Lieblings-Chili. Wenn man es richtig sauber entkernt ist es auch gar nicht scharf. Das scharfe an der Chili sind die Kerne und die "Venen".

should become:

„Chili Pasilla“ ist mein Lieblings-Chili. Wenn man es richtig sauber entkernt ist es auch gar nicht scharf. Das scharfe an der Chili sind die Kerne und die „Venen“.

Upvotes: 1

Views: 314

Answers (2)

Phil Gref
Phil Gref

Reputation: 987

I don't know if that's exactly what you are looking for, but here's the regex solution I would employ:

    public static string FixGermanQuotationMarks(string input)
    {
        var pattern = @"""([^""]*)""";
        return Regex.Replace(input, pattern, @"„$1“");
    }

It can be confusing with the quotes having to be escaped, so just imagine that the actual pattern would look more like this if it wasn't for escaping quotes: "([^"]*)". Alright, let's break this down:

  • " This matches your opening "regular" quote

  • ( This is to capture the content that is surrounded by the quotes. If you don't know what that means, you'll see in a minute

  • [^"] This matches everything that is not a quote (letters, numbers, whitespace, etc) The ^ is the negation operator when creating regexes, so ^" means *everything but* "

  • * This means that you can have zero or more of the previous item, which, in our case, was any character but the quote character. This is to make sure you capture as many letters as there are between the quotes.

  • )We close our capture group

  • " This matches the closing quote

Now, what did I mean by capture group ? It just means that, in the case of a match, we can actually reuse part of the match when the time comes to replace the content of the match in the original text. In our case, all we are interested about is the content that's between the two quotes, which is why we captured it. We can refer to what we have captured by using $1, which refers to the first (and in our case, the only) capture group. We then simply place this captured text between the German quotes, and use the resulting string to replace the whole match. As I mentionned before, it can be confusing when looking at the code I posted to see so many quotes, but a string literal has to be escaped using them.

After this, you only need to call the method like so:

var input = @"""Chili Pasilla"" ist mein Lieblings-Chili.";
var germanified = FixGermanQuotationMarks(input);

Hope this clarifies the regex method.

Upvotes: 4

Rufus L
Rufus L

Reputation: 37050

You could write an extension method on the string class to do it:

EDIT Based on good feedback, used a StringBuilder in extension method for better performance.

public static class StringExtensions
{
    /// <summary>
    /// Replaces every odd straight quote with '„' and every even straight quote with '“'.
    /// </summary>
    /// <param name="source">The string acting as the source for replacements.</param>
    /// <returns>A string with replacements made.</returns>
    public static string ReplaceStraightQuotes(this string source)
    {
        if (source == null) return null;

        var result = new StringBuilder(source);

        var lastIndex = source.IndexOf('"');
        int count = 0;

        while (lastIndex > -1)
        {
            char replaceQuote = (count++ % 2 == 0) ? '„' : '“';
            result.Replace('"', replaceQuote, lastIndex, 1);
            lastIndex = source.IndexOf('"', lastIndex + 1);
        }

        return result.ToString();
    }
}

Then you could use it like:

var result = "He said, \"Hello, you look lovely.\"";
Console.WriteLine(result);
Console.WriteLine(result.ReplaceStraightQuotes());

Output:

result = "He said, \"Hello, you look lovely.\""

result.ReplaceStraightQuotes() = "He said, „Hello, you look lovely.“"

Upvotes: 3

Related Questions