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()}),
60 if constexpr (
sizeof...(Args) > 0) {
61 mArgs.reserve(
sizeof...(Args), 0);
62 (mArgs.push_back(std::forward<Args>(args)), ...);
67 std::string message()
const noexcept override {
return message(ll::i18n::getDefaultLocaleCode()); }
68 std::string message(std::string_view localeCode)
const noexcept override try {
69 auto pattern = mI18n->get(mKey, localeCode.empty() ? ll::i18n::getDefaultLocaleCode() : localeCode);
70 if (!pattern.empty())
try {
71 return fmt::vformat(pattern, mArgs);
73 return fmt::vformat(mKey, mArgs);
78 std::string
const& key()
const noexcept {
return mKey; }
79 fmt::dynamic_format_arg_store<fmt::format_context>
const& args()
const noexcept {
return mArgs; }
84#ifdef LL_I18N_COLLECT_STRINGS
85#include "ll/api/reflection/TypeName.h"
87#ifndef LL_I18N_STRING_LITERAL_TYPE
88#define LL_I18N_STRING_LITERAL_TYPE ::ll::FixedStrWithLoc
91namespace ll::i18n::detail {
92template <LL_I18N_STRING_LITERAL_TYPE str>
94#ifndef LL_I18N_COLLECT_STRINGS_CUSTOM
95template <LL_I18N_STRING_LITERAL_TYPE str>
97 static inline int _ = [] {
98 fmt::print(
"\"{0}\": \"{0}\", // at {1}\n", str.sv(), str.loc().toString());
105#ifndef LL_I18N_STRING_LITERAL_TYPE
106#define LL_I18N_STRING_LITERAL_TYPE ::ll::FixedString
111template <LL_I18N_STRING_LITERAL_TYPE Fmt,
typename... Args>
112[[nodiscard]]
inline Unexpected makeI18nStringError(Args&&... args)
noexcept {
113#ifdef LL_I18N_COLLECT_STRINGS
114 static i18n::detail::TrStrOut<Fmt> e{};
116 return makeError<i18n::I18nStringError>(fmt::format_string<Args...>(Fmt.sv()), std::forward<Args>(args)...);
120namespace ll::inline literals::inline i18n_literals {
121template <LL_I18N_STRING_LITERAL_TYPE Fmt>
122[[nodiscard]]
constexpr auto operator""_tr() {
123#ifdef LL_I18N_COLLECT_STRINGS
124 static i18n::detail::TrStrOut<Fmt> e{};
126 return [=]<
class... Args>(Args&&... args) {
127 [[maybe_unused]]
static constexpr auto checker = fmt::format_string<Args...>(Fmt.sv());
128 return fmt::vformat(i18n::getInstance().get(Fmt.sv(), {}), fmt::make_format_args(args...));
131template <LL_I18N_STRING_LITERAL_TYPE Fmt>
132[[nodiscard]]
constexpr auto operator""_trl() {
133#ifdef LL_I18N_COLLECT_STRINGS
134 static i18n::detail::TrStrOut<Fmt> e{};
136 return [=]<
class... Args>(std::string_view localeCode, Args&&... args) {
137 [[maybe_unused]]
static constexpr auto checker = fmt::format_string<Args...>(Fmt.sv());
138 return fmt::vformat(i18n::getInstance().get(Fmt.sv(), localeCode), fmt::make_format_args(args...));