Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Go 1.18 strings.Title() is deprecated. What to use now? And how?

Tags:

go

As suggested here names of people should be capitalized like John William Smith.

I'm writing a small software in Golang which gets last and first name from user's form inputs.

Until Go 1.18 I was using:

lastname = strings.Title(strings.ToLower(strings.TrimSpace(lastname)))
firstname = strings.Title(strings.ToLower(strings.TrimSpace(firstname)))

It works but now Go 1.18 has deprecated strings.Title().

They suggest to use golang.org/x/text/cases instead.

So I think I should change my code in something like this:

caser := cases.Title(language.Und)

lastname = caser.Title(strings.ToLower(strings.TrimSpace(lastname)))
firstname = caser.Title(strings.ToLower(strings.TrimSpace(firstname)))

It works the same as before.

The difference is for Dutch word like ijsland that should be titled as IJsland and not Ijsland.

The question

In the line caser := cases.Title(language.Und) I'm using Und because I don't know what language Tag to use.

Should I use language.English or language.AmericanEnglish or other?

So far it was like strings.Title() was using Und or English?

like image 568
Fred Hors Avatar asked Sep 02 '25 16:09

Fred Hors


2 Answers

As mentioned in documentation strings.Title is deprecated and you should use cases.Title instead.

Deprecated: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead.

Here is an example code of how to use it as from two perspectives:

// Straightforward approach
caser := cases.Title(language.BrazilianPortuguese)
titleStr := caser.String(str)

// Transformer interface aware approach
src := []byte(s)
dest := []byte(s) // dest can also be `dest := src`
caser := cases.Title(language.BrazilianPortuguese)
_, _, err := caser.Transform(dest, src, true)

Make sure to take a look on the transform.Transformer.Transform and cases.Caser in order to understand what each parameter and return values mean, as well as the tool's limitations. For example:

A Caser may be stateful and should therefore not be shared between goroutines.

Regarding what language to use, you should be aware of their difference in the results, besides that, you should be fine with any choice. Here is a copy from 煎鱼's summary on the differences that cleared it for me:

Go Playground: https://go.dev/play/p/xp59r1BkC9L

func main() {
    src := []string{
        "hello world!",
        "i with dot",
        "'n ijsberg",
        "here comes O'Brian",
    }
    for _, c := range []cases.Caser{
        cases.Lower(language.Und),
        cases.Upper(language.Turkish),
        cases.Title(language.Dutch),
        cases.Title(language.Und, cases.NoLower),
    } {
        fmt.Println()
        for _, s := range src {
            fmt.Println(c.String(s))
        }
    }
}

With the following output

hello world!
i with dot
'n ijsberg
here comes o'brian

HELLO WORLD!
İ WİTH DOT
'N İJSBERG
HERE COMES O'BRİAN

Hello World!
I With Dot
'n IJsberg
Here Comes O'brian

Hello World!
I With Dot
'N Ijsberg
Here Comes O'Brian
like image 99
Eduardo Pacheco Avatar answered Sep 04 '25 16:09

Eduardo Pacheco


So far it was like strings.Title() was using Und or English?

strings.Title() works based on ASCII, where cases.Title() works based on Unicode, there is no way to get the exact same behavior.

Should I use language.English or language.AmericanEnglish or other?

language.English, language.AmericanEnglish and language.Und all seem to have the same Title rules. Using any of them should get you the closest to the original strings.Title() behavior as you are going to get.

The whole point of using this package with Unicode support is that it is objectively more correct. So pick a tag appropriate for your users.

like image 29
Dylan Reimerink Avatar answered Sep 04 '25 16:09

Dylan Reimerink