3#include "ll/api/Expected.h"
4#include "ll/api/base/Concepts.h"
5#include "ll/api/base/FixedString.h"
12#include "fmt/chrono.h"
14#include "fmt/compile.h"
15#include "fmt/format.h"
17#include "fmt/ranges.h"
24LLNDAPI std::string_view getDefaultLocaleCode();
28 std::unique_ptr<Impl> impl;
34 LLNDAPI Expected<> load(std::filesystem::path
const& path)
noexcept;
38 LLAPI
void set(std::string_view localeCode, std::string_view key, std::string_view value);
40 LLNDAPI std::string_view get(std::string_view key, std::string_view localeCode)
const;
43inline I18n& getInstance() {
48class I18nStringError :
public ErrorInfoBase {
50 gsl::not_null<I18n*> mI18n;
52 fmt::dynamic_format_arg_store<fmt::format_context> mArgs;
55 template <
typename... Args>
56 constexpr explicit I18nStringError(fmt::format_string<Args...> fmt, Args&&... args)
57 : mI18n(std::addressof(ll::i18n::getInstance())),
58 mKey(std::string{fmt.get().begin(), fmt.get().end()}) {
59 if constexpr (
sizeof...(Args) > 0) {
61 mArgs.reserve(
sizeof...(Args), fmt::detail::count_named_args<Args...>());
63 if constexpr (fmt::detail::is_named_arg<std::decay_t<Args>>()) {
65 mArgs.push_back(fmt::arg(std::forward<Args>(args).name, std::forward<Args>(args).value));
67 mArgs.push_back(std::forward<Args>(args));
75 std::string message()
const noexcept override {
return message(ll::i18n::getDefaultLocaleCode()); }
76 std::string message(std::string_view localeCode)
const noexcept override try {
77 auto pattern = mI18n->get(mKey, localeCode.empty() ? ll::i18n::getDefaultLocaleCode() : localeCode);
78 if (!pattern.empty())
try {
79 return fmt::vformat(pattern, mArgs);
81 return fmt::vformat(mKey, mArgs);
86 std::string
const& key()
const noexcept {
return mKey; }
87 fmt::dynamic_format_arg_store<fmt::format_context>
const& args()
const noexcept {
return mArgs; }
92#ifdef LL_I18N_COLLECT_STRINGS
93#include "ll/api/reflection/TypeName.h"
95#ifndef LL_I18N_STRING_LITERAL_TYPE
96#define LL_I18N_STRING_LITERAL_TYPE ::ll::FixedStrWithLoc
99namespace ll::i18n::detail {
100template <LL_I18N_STRING_LITERAL_TYPE str>
102#ifndef LL_I18N_COLLECT_STRINGS_CUSTOM
103template <LL_I18N_STRING_LITERAL_TYPE str>
105 static inline int _ = [] {
106 fmt::print(
"\"{0}\": \"{0}\", // at {1}\n", str.sv(), str.loc().toString());
113#ifndef LL_I18N_STRING_LITERAL_TYPE
114#define LL_I18N_STRING_LITERAL_TYPE ::ll::FixedString
119template <LL_I18N_STRING_LITERAL_TYPE Fmt,
typename... Args>
120[[nodiscard]]
inline Unexpected makeI18nStringError(Args&&... args)
noexcept {
121#ifdef LL_I18N_COLLECT_STRINGS
122 static i18n::detail::TrStrOut<Fmt> e{};
124 return makeError<i18n::I18nStringError>(fmt::format_string<Args...>(Fmt.sv()), std::forward<Args>(args)...);
128namespace ll::inline literals::inline i18n_literals {
129template <LL_I18N_STRING_LITERAL_TYPE Fmt>
130[[nodiscard]]
constexpr auto operator""_tr() {
131#ifdef LL_I18N_COLLECT_STRINGS
132 static i18n::detail::TrStrOut<Fmt> e{};
134 return [=]<
class... Args>(Args&&... args) {
135 [[maybe_unused]]
static constexpr auto checker = fmt::format_string<Args...>(Fmt.sv());
136 return fmt::vformat(i18n::getInstance().get(Fmt.sv(), {}), fmt::make_format_args(args...));
139template <LL_I18N_STRING_LITERAL_TYPE Fmt>
140[[nodiscard]]
constexpr auto operator""_trl() {
141#ifdef LL_I18N_COLLECT_STRINGS
142 static i18n::detail::TrStrOut<Fmt> e{};
144 return [=]<
class... Args>(std::string_view localeCode, Args&&... args) {
145 [[maybe_unused]]
static constexpr auto checker = fmt::format_string<Args...>(Fmt.sv());
146 return fmt::vformat(i18n::getInstance().get(Fmt.sv(), localeCode), fmt::make_format_args(args...));