format_intl
format_intl adapts the number symbols and grouping rules in
intl for use with
format. It keeps format independent of
intl while letting an application opt into locale-aware number formatting.
Installation
Add both packages to the application that creates the formatting engine:
dependencies:
format: ^4.0.0
format_intl: ^1.0.0
Under Flutter there is one more constraint to satisfy, and it is not this
package's: flutter_localizations pins intl to a single exact version, so
that pin and the constraint here have to overlap. The intl range above spans
both versions Flutter pins — 0.19.0 up to Flutter 3.31.x and 0.20.2 from
3.32.0 — so the two overlap on every Flutter from 3.27.0, which is also the
first one format itself installs on.
Which intl your application resolves is visible in the output
This package is an adapter: it reports the symbols the resolved intl carries,
and that data is not identical across the range. Of the 119 locales intl
ships, four differ:
| Locale | intl 0.19.0 |
0.20.2 | 0.20.3 |
|---|---|---|---|
en_ZA |
decimal ., group , |
decimal ,, group NBSP |
same as 0.20.2 |
de_CH, gsw, it_CH |
group ’ |
group ’ |
group ' |
Only en_ZA changes the decimal separator, so it is the one where a number can
be read wrongly rather than merely look different. Note that three of the four
already move inside a ^0.20.2 constraint: pinning the range up would not have
made the output version-independent, only narrower. Every other locale is
identical across all three versions.
Usage
Inject an IntlNumberLocale when constructing Format. The resulting engine
is independent of the package-level default API, so retain whichever method
tear-offs your application needs:
import 'package:format/format.dart';
import 'package:format_intl/format_intl.dart';
void main() {
final kazakh = Format(
numberLocale: IntlNumberLocale('kk_KZ'),
);
final formatKk = kazakh.format;
final sprintfKk = kazakh.sprintf;
print(formatKk('{:n}', 1234567.5));
print(sprintfKk('%.2f', 12.5));
}
Format provides four formatting method tear-offs:
formataccepts a brace-format template and up to ten positional values.formatWithaccepts a brace-format template pluspositionalandnamedcollections.sprintfaccepts a printf-style template and up to ten positional values.vsprintfaccepts a printf-style template and a list of values.
The n specifier applies the adapter's grouping rule automatically; it does
not need a grouping flag. The printf dialect uses the locale's decimal
separator, signs, exponent separator, and digits.
That exponent separator is worth knowing about before it surprises you: intl
spells it E for 108 of its 119 locales, so %e and %E produce the same
text under most of them and stop being distinguishable. Seven locales spell it
as something that is not a letter at all — ×10^ in sv, أس in ar_EG —
and there %E has nothing to uppercase either. Brace formatting is
unaffected, because {:e} does not read the locale at all; only {:n}
does. IntlNumberLocale supplies
symbols and grouping only: it does not round values. Precision and rounding
remain the responsibility of format. IntlNumberLocale does not select or
apply number notation, including compact or scientific notation; notation
remains the responsibility of format.
Decimal double values use Dart SDK conversion by default. Locale symbols are
applied after that conversion. Select the compatible profile when Python brace
or C++ printf rounding and exponent layout are required:
final compatibleKazakh = Format(
numberLocale: IntlNumberLocale('kk_KZ'),
doubleFormatMode: DoubleFormatMode.compatible,
);
DoubleSpecialValueSpelling.short selects nan/inf in Dart SDK mode;
compatible mode always uses those short spellings. These profile settings
belong to Format, not IntlNumberLocale.
Default-locale snapshot
Use IntlNumberLocale.fromDefault() when the intl current locale should be
chosen at construction time:
final locale = IntlNumberLocale.fromDefault();
final engine = Format(numberLocale: locale);
This takes an immutable snapshot of the locale's number symbols and grouping
rules. Changing Intl.defaultLocale later does not update an existing
IntlNumberLocale or Format; construct a new adapter and engine to use the
new default.
Localized digits are a Dart extension
IntlNumberLocale also maps ASCII digits to the locale's ZERO_DIGIT symbol.
That applies to both brace and printf formatting. Localized digits and locale
specific signs or exponent symbols are Dart extensions provided by format's
NumberLocale interface; they go beyond the C locale behavior that printf
compatibility targets.
Libraries
- format_intl
- Locale data from
intlas aNumberLocalefor theformatpackage.