Since the introduction of format strings in Fortran in the 50s pretty much all major programming languages used them in their text formatting and I/O APIs:
One notable exception is C++ iostreams that use operator overloading and per-stream state manipulation to control formatting. At this point stateful APIs have pretty much proved to be a failure in terms of usability and performance and many C++ programmers prefer *printf instead.
However, format strings in C have a bad reputation because of lack of type safety: users must encode type information together with formatting information. If the user-specified and actual types don’t match we have an undefined behavior (godbolt):
Fortunately, modern compilers can diagnose such errors at compile time for literal format strings but this is an opt-in which is not ideal. Encoding type information by hand is not only error-prone but also cumbersome as this table from the documentation of the C stdint.h header illustrates:
Formatting facilities in languages other than C are usually type-safe. For example, in Python you get an exception when trying to format a string as an integer: