# How to Use Positional Arguments in fmtlib for Localization

> Master positional arguments in fmtlib for localization. Apply locale-specific formatting to arguments precisely and control ordering effortlessly. Enhance your internationalized applications today.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-10

---

**The {fmt} library allows you to combine explicit positional indices like `{0}` or `{1}` with the `L` format specifier to apply locale-specific formatting (digit grouping, decimal separators) to individual arguments while maintaining complete control over argument ordering.**

The **fmtlib/fmt** repository provides a type-safe C++ formatting library that handles complex localization requirements through its positional argument syntax. By referencing specific argument indices in your format string, you can reorder values for different languages and apply localized formatting only where needed. This article examines the internal parsing architecture and practical usage patterns for positional arguments in fmtlib for localization based on the current source tree.

## Understanding the Syntax

A replacement field in {fmt} follows the structure `{index[:format][L][!conversion][width][precision]}`. The **argument index** selects which positional argument to format, while the **`L` specifier** activates locale-aware output for that specific field. These components operate independently, allowing precise control over both argument selection and localization.

The parser processes these fields in two distinct stages. First, it tokenizes the format string and builds a **format_specs** object for each replacement field. When the parser encounters an explicit index, it stores that positional reference; when it encounters `L`, it sets the localization flag via `format_specs::localized()`.

## Core Architecture

### Argument Index Resolution

In [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), the format string parser resolves positional arguments during the initial tokenization phase. According to the source around line 2218, the library constructs a `format_specs` object that captures both the explicit **argument index** (if provided) and the presence of the `L` conversion specifier. If you omit the index, the library uses the "next argument" rule, automatically incrementing to the following positional parameter.

### Localization Flag Processing

The **`format_specs::localized()`** method indicates whether the `L` specifier is present in the current field. This flag is defined in [`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h) alongside related utilities like `localized_mask` and `set_localized()`. The flag remains independent of the argument index, meaning you can apply localization to any positional argument regardless of its position in the argument list.

### Locale-Aware Write Path

During the final formatting stage, the library checks the localization flag to determine which output path to take. In [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) around line 2371, the code invokes **locale-aware write functions** (`write_loc`) when `localized()` returns true. These functions utilize helpers from [`include/fmt/locale.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/locale.h), such as `detail::decimal_point` (referenced around line 2793), to retrieve the correct decimal separators and digit grouping characters for the current locale.

## Practical Code Examples

The following examples demonstrate combining positional arguments with localization in various contexts:

```cpp
#include <fmt/core.h>
#include <fmt/locale.h>
#include <locale>

int main() {
  // 1️⃣ Simple positional arguments (no localization)
  std::string s1 = fmt::format("I’d rather be {1} than {0}.", "right", "happy");
  // → "I’d rather be happy than right."

  // 2️⃣ Localized integer with grouping (uses the current locale)
  std::locale loc("en_US.UTF-8");          // comma as thousands separator
  std::string s2 = fmt::format(loc, "Amount: {0:L}", 1234567);
  // → "Amount: 1,234,567"

  // 3️⃣ Mixing positional index and localization with precision
  double v = 12345.6789;
  std::string s3 = fmt::format(loc, "Value: {1:.2L} ({0})", "raw", v);
  // → "Value: 12,345.68 (raw)"

  // 4️⃣ Localized date/time (uses fmt::chrono.h, also supports positional args)
  #include <fmt/chrono.h>
  auto now = std::chrono::system_clock::now();
  std::string s4 = fmt::format(loc, "Current time: {0:%cL}", now);
  // → locale‑specific full date‑time string
}

```

## Key Implementation Files

Understanding the following source files provides deeper insight into how positional arguments and localization interact:

- **[`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h)** — Contains the core parser that handles `format_specs` construction, argument index resolution, and the `write_loc` implementation for localized output.

- **[`include/fmt/core.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/core.h)** — Defines the `localized_mask` and `set_localized()` utilities used during format specification parsing.

- **[`include/fmt/locale.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/locale.h)** — Provides locale-aware helpers including `detail::decimal_point` for retrieving culture-specific separators.

- **[`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h)** — Implements localized date-time formatting using the same positional argument mechanics.

- **[`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h)** — Demonstrates POSIX-style positional syntax (`*1$`) for width and precision in printf-compatible APIs.

## Summary

- **Positional arguments** use explicit indices (`{0}`, `{1}`) to select specific arguments, enabling reordering for different languages or reuse of the same argument multiple times.
- The **`L` specifier** activates locale-aware formatting for individual fields, applying digit grouping and proper decimal separators based on the provided locale.
- The **parsing architecture** separates argument index resolution from localization flag detection in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), allowing these features to combine freely.
- **Locale-aware output** occurs through specialized write paths that consult `detail::decimal_point` and related utilities from [`include/fmt/locale.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/locale.h).
- Both features work with **chrono types** via [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h), supporting localized date and time formatting with positional indices.

## Frequently Asked Questions

### Can positional arguments be used with automatic indexing in the same format string?

No, {fmt} requires you to choose between automatic indexing (omitting indices) and manual positional indexing. If you provide an explicit index for any argument, you must provide explicit indices for all arguments in that format string. The parser enforces this consistency to prevent ambiguity about which argument corresponds to which replacement field.

### Does the `L` specifier work with all data types?

The `L` specifier primarily affects arithmetic types (integers, floating-point numbers) and chrono types. For arithmetic types, it enables digit grouping and locale-specific decimal points. For chrono types in [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h), it produces locale-specific date and time representations. String and pointer types generally ignore the `L` specifier because they do not have locale-specific formatting variations.

### How does fmtlib handle locales with different grouping conventions?

The library uses the **`detail::decimal_point`** helper and related locale facets defined in [`include/fmt/locale.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/locale.h) to query the current locale's `numpunct` facet. This provides the thousands separator character (such as comma, period, or space) and the grouping pattern (such as three digits or Indian-style grouping). The `write_loc` function in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) applies these settings when the `L` flag is set.

### Are positional arguments supported in printf-style formatting?

Yes, {fmt} supports POSIX-style positional arguments in its printf API via [`include/fmt/printf.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/printf.h). You can use the `%1$d` syntax to reference the first argument, `%2$d` for the second, and so on. The library also supports positional width and precision using the `*1$` notation, where the asterisk references a specific argument for the width or precision value.