Skip to content

Commit

Permalink
Remove formatUnchecked and extend i18n api with format check. (#1274)
Browse files Browse the repository at this point in the history
While we can not check translated string, it is still make sense
to check the original string at compile time.

It also simplify the usage and solve the issue that runtime_format_string
is not available at c++20.
  • Loading branch information
wengxt authored Feb 20, 2025
1 parent eb13b22 commit 274e863
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 39 deletions.
24 changes: 11 additions & 13 deletions src/im/keyboard/keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ std::vector<InputMethodEntry> KeyboardEngine::listInputMethods() {
auto language = findBestLanguage(isoCodes, layoutInfo.description,
layoutInfo.languages);
auto description =
formatUnchecked(_("Keyboard - {0}"),
D_("xkeyboard-config", layoutInfo.description));
_("Keyboard - {0}", D_("xkeyboard-config", layoutInfo.description));
auto uniqueName = imNamePrefix + layoutInfo.name;
if (uniqueName == "keyboard-us") {
usExists = true;
Expand All @@ -271,10 +270,10 @@ std::vector<InputMethodEntry> KeyboardEngine::listInputMethods() {
!variantInfo.languages.empty()
? variantInfo.languages
: layoutInfo.languages);
auto description = formatUnchecked(
_("Keyboard - {0} - {1}"),
D_("xkeyboard-config", layoutInfo.description),
D_("xkeyboard-config", variantInfo.description));
auto description =
_("Keyboard - {0} - {1}",
D_("xkeyboard-config", layoutInfo.description),
D_("xkeyboard-config", variantInfo.description));
auto uniqueName = stringutils::concat(imNamePrefix, layoutInfo.name,
"-", variantInfo.name);

Expand Down Expand Up @@ -311,13 +310,12 @@ std::vector<InputMethodEntry> KeyboardEngine::listInputMethods() {
if (uniqueName == "keyboard-us") {
usExists = true;
}
result.push_back(std::move(
InputMethodEntry(
uniqueName,
formatUnchecked(_("{0} (Not Available)"), *desc), *lang,
"keyboard")
.setLabel(*label)
.setIcon("input-keyboard")));
result.push_back(
std::move(InputMethodEntry(uniqueName,
_("{0} (Not Available)", *desc),
*lang, "keyboard")
.setLabel(*label)
.setIcon("input-keyboard")));
}
}
} else {
Expand Down
49 changes: 44 additions & 5 deletions src/lib/fcitx-utils/i18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
#define _FCITX_UTILS_I18N_H_

#include <string>
#include <utility>
#include <fcitx-utils/fcitxutils_export.h>
#if __cplusplus >= 202002L
#include <format>
#endif

namespace fcitx {

Expand All @@ -28,19 +32,54 @@ translateDomainCtx(const char *domain, const char *ctx, const std::string &s);
FCITXUTILS_EXPORT const char *
translateDomainCtx(const char *domain, const char *ctx, const char *s);
FCITXUTILS_EXPORT void registerDomain(const char *domain, const char *dir);

#if __cplusplus >= 202002L
template <typename... Args>
auto translate(std::format_string<Args...> s, Args &&...args)
-> std::enable_if_t<(sizeof...(Args) >= 1), std::string> {
return std::vformat(translate(std::string(s.get())),
std::make_format_args(args...));
}

template <typename... Args>
auto translateCtx(const char *ctx, std::format_string<Args...> s,
Args &&...args)
-> std::enable_if_t<(sizeof...(Args) >= 1), std::string> {
return std::vformat(translateCtx(ctx, std::string(s.get())),
std::make_format_args(args...));
}

template <typename... Args>
auto translateDomain(const char *domain, std::format_string<Args...> s,
Args &&...args)
-> std::enable_if_t<(sizeof...(Args) >= 1), std::string> {
return std::vformat(translateDomain(domain, std::string(s.get())),
std::make_format_args(args...));
}

template <typename... Args>
auto translateDomainCtx(const char *domain, const char *ctx,
std::format_string<Args...> s, Args &&...args)
-> std::enable_if_t<(sizeof...(Args) >= 1), std::string> {
return std::vformat(translateDomainCtx(domain, ctx, std::string(s.get())),
std::make_format_args(args...));
}
#endif

} // namespace fcitx

#ifndef FCITX_NO_I18N_MACRO

#ifdef FCITX_GETTEXT_DOMAIN
#define _(x) ::fcitx::translateDomain(FCITX_GETTEXT_DOMAIN, x)
#define C_(c, x) ::fcitx::translateDomainCtx(FCITX_GETTEXT_DOMAIN, c, x)
#define _(...) ::fcitx::translateDomain(FCITX_GETTEXT_DOMAIN, __VA_ARGS__)
#define C_(c, ...) \
::fcitx::translateDomainCtx(FCITX_GETTEXT_DOMAIN, c, __VA_ARGS__)
#else
#define _(x) ::fcitx::translate(x)
#define C_(c, x) ::fcitx::translateCtx(c, x)
#define _(...) ::fcitx::translate(__VA_ARGS__)
#define C_(c, ...) ::fcitx::translateCtx(c, __VA_ARGS__)
#endif

#define D_(d, x) ::fcitx::translateDomain(d, x)
#define D_(d, ...) ::fcitx::translateDomain(d, __VA_ARGS__)

#define NC_(c, x) (x)
#define N_(x) (x)
Expand Down
7 changes: 0 additions & 7 deletions src/lib/fcitx-utils/misc_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <fcitx-utils/endian_p.h>
#include <fcitx-utils/environ.h>
#include <fcitx-utils/macros.h>
#include <format>
#include "config.h" // IWYU pragma: keep

#ifdef _WIN32
Expand Down Expand Up @@ -339,12 +338,6 @@ static inline uint32_t FromLittleEndian32(const T *d) {
return le32toh(t);
}

template <typename... Args>
FCITX_NODISCARD inline std::string formatUnchecked(std::string_view fmt,
Args &&...args) {
return std::vformat(fmt, std::make_format_args(args...));
}

} // namespace fcitx

#endif // _FCITX_UTILS_MISC_P_H_
19 changes: 8 additions & 11 deletions src/lib/fcitx/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,7 @@ void InstancePrivate::buildDefaultGroup() {
if (imLayouts.size() == 1) {
groupName = _("Default");
} else {
groupName =
formatUnchecked(_("Group {}"), imManager_.groupCount() + 1);
groupName = _("Group {}", imManager_.groupCount() + 1);
}
imManager_.addEmptyGroup(groupName);
groupOrders.push_back(groupName);
Expand Down Expand Up @@ -421,17 +420,16 @@ void InstancePrivate::showInputMethodInformation(InputContext *ic) {
} else if (subMode.empty()) {
display = std::move(name);
} else {
display = formatUnchecked(_("{0} ({1})"), name, subMode);
display = _("{0} ({1})", name, subMode);
}
} else if (entry) {
display = formatUnchecked(_("{0} (Not available)"), entry->name());
display = _("{0} (Not available)", entry->name());
} else {
display = _("(Not available)");
}
if (!globalConfig_.compactInputMethodInformation() &&
imManager.groupCount() > 1) {
display = formatUnchecked(_("Group {0}: {1}"),
imManager.currentGroup().name(), display);
display = _("Group {0}: {1}", imManager.currentGroup().name(), display);
}
inputState->showInputMethodInformation(display);
}
Expand Down Expand Up @@ -467,9 +465,8 @@ void InstancePrivate::navigateGroup(InputContext *ic, const Key &key,
notifications_->call<INotifications::showTip>(
"enumerate-group", _("Input Method"), "input-keyboard",
_("Switch group"),
formatUnchecked(
_("Switch group to {0}"),
imManager_.groups()[inputState->pendingGroupIndex_]),
_("Switch group to {0}",
imManager_.groups()[inputState->pendingGroupIndex_]),
3000);
}
}
Expand Down Expand Up @@ -697,8 +694,8 @@ Instance::Instance(int argc, char **argv) {
d->notifications_->call<INotifications::showTip>(
"enumerate-group", _("Input Method"), "input-keyboard",
_("Switch group"),
formatUnchecked(_("Switched group to {0}"),
d->imManager_.currentGroup().name()),
_("Switched group to {0}",
d->imManager_.currentGroup().name()),
3000);
}
d->lastGroup_ = newGroup;
Expand Down
4 changes: 1 addition & 3 deletions src/modules/xcb/xcbconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,7 @@ void XCBConnection::navigateGroup(const Key &key, bool forward) {
parent_->notifications()->call<INotifications::showTip>(
"enumerate-group", _("Input Method"), "input-keyboard",
_("Switch group"),
formatUnchecked(_("Switch group to {0}"),
imManager.groups()[groupIndex_]),
3000);
_("Switch group to {0}", imManager.groups()[groupIndex_]), 3000);
}
}

Expand Down

0 comments on commit 274e863

Please sign in to comment.