Localizing spin box prefixes/suffixes
KDE Frameworks 6.5 brings a little new feature for localizing prefix and suffix texts in spin boxes. It’s also a good reminder of the level of detail we have to pay attention to when preparing our software for being translated.
The problem
Qt spin boxes can have inline prefix and suffix strings. That’s commonly used for units.
There’s multiple challenges when localizing this:
- Plurals: Depending on the selected quantity different plural forms for prefixes/suffixes might be needed (e.g. “1 cake” vs “3 cakes”). How many plural forms there are depends on the language and can be anywhere between none (e.g. Japanese) and six (e.g. Arabic). CLDR’s Language Plural Rules gives you an idea of the complexity.
- Word order: Not all languages place those texts in the same position. For a percent value for example English
uses the
%sign as a suffix, while Turkish uses it as a prefix.
So just setting a fixed string doesn’t cut it.
Existing solutions
None of that is new, and for the plural handling we do have an existing solution in form of KPluralHandlingSpinBox in KF::TextWidgets. It takes a suffix in form of a KLocalizedString, which it reevaluates each time its value changes to show the correct plural form.
This works but has a number of downsides:
- It’s not solving the word order problem, and it’s only handing suffixes.
- It’s using inheritance and thus is harder to integrate with custom or otherwise more complex existing spin box code.
- The use of inheritance is also limiting it to
QSpinBox, not helping with e.g.QDoubleSpinBox.
New API in KF::I18n
Starting with an idea by Emir Sarı and Lukas Sommer for a solution to the word ordering problem and a suggestion by me to generalize the same approach to cover plural handling as well we ended up with two new methods in KF::I18n.
KLocalization::setupSpinBoxFormatString is the one you’ll most commonly need. It allows to set a KLocalizedString format
string on any spin box instance. That format string must contain the special placeholder %v, which
represents the current spin box value.
Texts before the %v end up in the prefix and the part after it in the suffix, giving translations control over the word order.
This can be used both with and without considering plural forms, as shown in the example below.
// with plural
QSpinBox spinBox;
KLocalization::setupSpinBoxFormatString(&spinBox, ki18np("Baking %v cake", "Baking %v cakes"));
// without plural
QDoubleSpinBox doubleSpinBox;
KLocalization::setupSpinBoxFormatString(&doubleSpinBox, ki18n("%v%"));As this isn’t relying on inheritance it can be used on QSpinBox, QDoubleSpinBox or any subclass thereof. Being part of
KF::I18n also means this is very likely available without needing additional dependencies. All of this should help with a
much wider adoption than we ever had for KPluralHandlingSpinBox.
The second new method is KLocalization::retranslateSpinBoxFormatString, which explicitly triggers reevaluating
the format string. That’s automatically called when the spin box value changes, but if you are for example supporting
runtime language changes you might have the need for manually triggering this as well.
What’s left to do
We need to make use of this. It’s an easy way to contribute, and helps making our software better in other languages than English :)
There’s also the question how to address these issues in QML UIs. Qt’ QML spin box control doesn’t have support for inline prefixes/suffixes, but the problems don’t go away by placing the those texts on the outside.