I/O lists are the preferred way to concatenate data like this in Erlang. You can easily do dynamic stuff, e.g. ["foo", dynamic(Input), "bar"] which will get rendered properly and efficiently when it leaves the system through a socket, file, standard out etc.
Is the word order the only thing that may change
with language? I used to teach students about
internationalisation, and there’s a long long list
Dates and times are a big one.
It’s not just that months and days have different
names in different languages, the whole structure
of the calendar may be different. What if your
customer wants dates displayed on the Hindu
traditional calendar? (In this country there are
the Gregorian calendar with English words, the
Gregorian calendar with Maori words, and N versions
of “the” traditional Maori calendar, with different
ideas about when to start a new year. You are NOT
going to be able to format dates on any of the
traditional calendars with C’s strftime() or its
analogues in other languages.)
Numbers. Different rules for which characters are
grouping characters and where they go. And of
course there are different digits. Unicode 13 had
64 honest-to-goodness sets of digits, not counting
Currency. It’s not just formatting, it’s conversion.
I have free account with OpenExchangeRates.com, but
that limits how often I can access it. Speaking of
formatting, there is a fundamental problem with
relying on C’s locale support. If you want guidance
for how to display Yuan in Australia, you’re out of
luck. The C locale model says “if you’re in Australia
you only deal with Australian dollars, so XXXX you.”
This really is not the kind of stuff that you can
reasonably encode in a string.
Weights and measures. Obvious. But there are formatting
differences as well as differences in what the units are.
Place names. The same place may have different names
even in the same country (Wellington vs Pōneke, for
example). We really need a decent multilingual gazeteer.