HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
translate.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "language.hpp"
8#include "translation.hpp"
9#include "../forward_value.hpp"
10#include "../cast.hpp"
11#include "../os_settings.hpp"
12#include <memory>
13#include <string>
14#include <string_view>
15#include <tuple>
16
17namespace hi::inline v1 {
18namespace detail {
20public:
21 virtual ~translate_args_base() {}
22
26 [[nodiscard]] virtual std::string format(std::string_view fmt) const noexcept = 0;
27
32 [[nodiscard]] virtual std::string format(std::locale const &loc, std::string_view fmt) const noexcept = 0;
33
37 [[nodiscard]] virtual long long n() const noexcept = 0;
38
41 [[nodiscard]] virtual std::unique_ptr<translate_args_base> unique_copy() const noexcept = 0;
42
43 [[nodiscard]] virtual bool equal_to(translate_args_base const &rhs) const noexcept = 0;
44
45 [[nodiscard]] bool friend operator==(translate_args_base const &lhs, translate_args_base const &rhs) noexcept
46 {
47 return lhs.equal_to(rhs);
48 }
49};
50
55template<typename... Values>
57public:
58 translate_args(translate_args &&) noexcept = default;
59 translate_args(translate_args const &) noexcept = default;
60 translate_args &operator=(translate_args &&) noexcept = default;
61 translate_args &operator=(translate_args const &) noexcept = default;
62
75 template<typename... Args>
76 translate_args(Args const &...args) noexcept : _values(args...)
77 {
78 }
79
81 {
82 return std::make_unique<translate_args>(*this);
83 }
84
85 [[nodiscard]] virtual bool equal_to(translate_args_base const &rhs) const noexcept
86 {
87 if (auto *rhs_ = dynamic_cast<translate_args const *>(&rhs)) {
88 return _values == rhs_->_values;
89 } else {
90 return false;
91 }
92 }
93
94 [[nodiscard]] std::string format(std::string_view fmt) const noexcept override
95 {
96 return std::apply(format_wrapper<Values const &...>, std::tuple_cat(std::tuple{fmt}, _values));
97 }
98
99 [[nodiscard]] std::string format(std::locale const &loc, std::string_view fmt) const noexcept override
100 {
101 return std::apply(format_locale_wrapper<Values const &...>, std::tuple_cat(std::tuple{loc, fmt}, _values));
102 }
103
104 template<std::size_t I>
105 [[nodiscard]] long long n_recurse() const noexcept
106 {
107 if constexpr (I < sizeof...(Values)) {
108 if constexpr (std::is_integral_v<decltype(std::get<I>(_values))>) {
109 return narrow_cast<long long>(std::get<I>(_values));
110 } else {
111 return n_recurse<I + 1>();
112 }
113 } else {
114 return 0;
115 }
116 }
117
118 [[nodiscard]] long long n() const noexcept override
119 {
120 return n_recurse<0>();
121 }
122
123private:
124 std::tuple<Values...> _values;
125
126 template<typename... Args>
127 static std::string format_wrapper(std::string_view fmt, Args const &...args)
128 {
129 return std::vformat(fmt, std::make_format_args(args...));
130 }
131
132 template<typename... Args>
133 static std::string format_locale_wrapper(std::locale const &loc, std::string_view fmt, Args const &...args)
134 {
135 return std::vformat(loc, fmt, std::make_format_args(args...));
136 }
137};
138
139template<typename... Args>
140translate_args(Args &&...) -> translate_args<forward_value_t<Args>...>;
141
142} // namespace detail
143
151public:
154 constexpr translate() noexcept : _msg_id(), _args(nullptr) {}
155
156 translate(translate &&) noexcept = default;
157 translate &operator=(translate &&) noexcept = default;
158
159 translate(translate const &other) noexcept : _msg_id(other._msg_id), _args(other._args ? other._args->unique_copy() : nullptr) {}
160
161 translate &operator=(translate const &other) noexcept
162 {
163 _msg_id = other._msg_id;
164 _args = other._args ? other._args->unique_copy() : nullptr;
165 return *this;
166 }
167
168 [[nodiscard]] constexpr bool empty() const noexcept
169 {
170 return _msg_id.empty();
171 }
172
175 [[nodiscard]] constexpr explicit operator bool() const noexcept
176 {
177 return not empty();
178 }
179
193 template<typename... Args>
194 translate(std::string_view msg_id, Args const &...args) noexcept :
195 _msg_id(msg_id), _args(sizeof...(Args) ? std::make_unique<detail::translate_args<forward_value_t<Args>...>>(args...) : nullptr)
196 {
197 }
198
205 [[nodiscard]] std::string operator()(std::vector<language *> const &languages = os_settings::languages()) const noexcept
206 {
207 if (_args) {
208 auto fmt = ::hi::get_translation(_msg_id, _args->n(), languages);
209 return _args->format(fmt);
210 } else {
211 return std::string{::hi::get_translation(_msg_id, 0, languages)};
212 }
213 }
214
222 [[nodiscard]] std::string
223 operator()(std::locale const &loc, std::vector<language *> const &languages = os_settings::languages()) const noexcept
224 {
225 if (_args) {
226 auto fmt = ::hi::get_translation(_msg_id, _args->n(), languages);
227 return _args->format(loc, fmt);
228 } else {
229 return std::string{::hi::get_translation(_msg_id, 0, languages)};
230 }
231 }
232
239 [[nodiscard]] friend bool operator==(translate const &lhs, translate const &rhs) noexcept
240 {
241 if (lhs._args == rhs._args) {
242 return lhs._msg_id == rhs._msg_id;
243 } else if (lhs._args and rhs._args) {
244 return lhs._msg_id == rhs._msg_id and *lhs._args == *rhs._args;
245 } else {
246 return false;
247 }
248 }
249
250private:
251 std::string _msg_id;
253};
254
255using tr = translate;
256
257} // namespace hi::inline v1
STL namespace.
Definition translate.hpp:19
virtual std::string format(std::string_view fmt) const noexcept=0
Format text from the arguments and the given format string.
virtual long long n() const noexcept=0
The numeric value of the first numeric argument.
virtual std::string format(std::locale const &loc, std::string_view fmt) const noexcept=0
Format text from the arguments and the given format string.
Delayed formatting.
Definition translate.hpp:56
long long n() const noexcept override
The numeric value of the first numeric argument.
Definition translate.hpp:118
std::unique_ptr< translate_args_base > unique_copy() const noexcept
Make a unique copy of the arguments.
Definition translate.hpp:80
std::string format(std::string_view fmt) const noexcept override
Format text from the arguments and the given format string.
Definition translate.hpp:94
std::string format(std::locale const &loc, std::string_view fmt) const noexcept override
Format text from the arguments and the given format string.
Definition translate.hpp:99
translate_args(Args const &...args) noexcept
Construct a translate arguments.
Definition translate.hpp:76
A localizable message.
Definition translate.hpp:150
friend bool operator==(translate const &lhs, translate const &rhs) noexcept
Compare two localizable messages.
Definition translate.hpp:239
translate(std::string_view msg_id, Args const &...args) noexcept
Construct a localizable message.
Definition translate.hpp:194
constexpr translate() noexcept
Construct an empty message.
Definition translate.hpp:154
std::string operator()(std::vector< language * > const &languages=os_settings::languages()) const noexcept
Translate and format the message.
Definition translate.hpp:205
std::string operator()(std::locale const &loc, std::vector< language * > const &languages=os_settings::languages()) const noexcept
Translate and format the message.
Definition translate.hpp:223
T tuple_cat(T... args)