HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
language_tag_intf.hpp
1// Copyright Take Vos 2022.
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 "iso_15924.hpp"
8#include "iso_3166.hpp"
9#include "iso_639.hpp"
10#include "../utility/utility.hpp"
11#include "../coroutine/module.hpp"
12#include "../algorithm/module.hpp"
13#include "../macros.hpp"
14#include <vector>
15#include <string_view>
16
17hi_export_module(hikogui.i18n.language_tag : intf);
18
19namespace hi { inline namespace v1 {
20
28hi_export class language_tag {
29public:
30 iso_639 language;
31 iso_15924 script;
32 iso_3166 region;
33 uint16_t _reserved = 0;
34
35 constexpr language_tag() noexcept {}
36 constexpr language_tag(language_tag const&) noexcept = default;
37 constexpr language_tag(language_tag&&) noexcept = default;
38 constexpr language_tag& operator=(language_tag const&) noexcept = default;
39 constexpr language_tag& operator=(language_tag&&) noexcept = default;
40
41 constexpr language_tag(iso_639 const& language, iso_15924 const& script = {}, iso_3166 const& region = {}) noexcept :
42 language(language), script(script), region(region)
43 {
44 }
45
46 constexpr language_tag(iso_639 const& language, iso_3166 const& region) noexcept : language_tag(language, {}, region) {}
47
60 language_tag(std::string_view str);
61
66 [[nodiscard]] static language_tag parse(std::string_view str);
67
71 {
72 return language.empty() and script.empty() and region.empty();
73 }
74
77 explicit operator bool() const noexcept
78 {
79 return not empty();
80 }
81
90 {
91 co_yield *this;
92 if (script and region) {
93 co_yield language_tag{language, region};
94 co_yield language_tag{language, script};
95 }
96 if (script or region) {
97 co_yield language_tag{language};
98 }
99 }
100
110 {
111 hilet check = expand();
112 for (hilet& tag : variants()) {
113 if (tag.expand() == check) {
114 co_yield tag;
115 }
116 }
117 }
118
122 {
123 auto r = make_vector(variants());
124
125 // And languages variants from expanded variants.
126 for (hilet variant : variants()) {
127 for (hilet expanded_variant : variant.expand().variants()) {
128 if (std::find(r.begin(), r.end(), expanded_variant) == r.end()) {
129 r.push_back(expanded_variant);
130 }
131 }
132 }
133 return r;
134 }
135
141
145 {
146 auto last_variant = *this;
147 for (hilet& variant : canonical_variants()) {
148 last_variant = variant;
149 }
150 return last_variant;
151 }
152
158 {
159 return expand().script;
160 }
161
167 {
168 return default_script().left_to_right();
169 }
170
171 [[nodiscard]] constexpr friend std::string to_string(language_tag const &rhs) noexcept
172 {
173 auto r = std::string{};
174 r += rhs.language.code();
175 if (rhs.script) {
176 r += '-';
177 r += rhs.script.code4();
178 }
179 if (rhs.region) {
180 r += "-";
181 r += rhs.region.code2();
182 }
183 return r;
184 }
185
188 [[nodiscard]] constexpr friend bool matches(language_tag const& lhs, language_tag const& rhs) noexcept
189 {
190 if (lhs.language and rhs.language and lhs.language != rhs.language) {
191 return false;
192 }
193 if (lhs.script and rhs.script and lhs.script != rhs.script) {
194 return false;
195 }
196 if (lhs.region and rhs.region and lhs.region != rhs.region) {
197 return false;
198 }
199 return true;
200 }
201
202 [[nodiscard]] constexpr friend bool operator==(language_tag const&, language_tag const&) noexcept = default;
203};
204
214
215}} // namespace hi::inline v1
216
217hi_export template<>
218struct std::hash<hi::language_tag> {
219 [[nodiscard]] size_t operator()(hi::language_tag const& rhs) const noexcept
220 {
221 return hi::hash_mix(
222 std::hash<hi::iso_639>{}(rhs.language),
223 std::hash<hi::iso_15924>{}(rhs.script),
224 std::hash<hi::iso_3166>{}(rhs.region));
225 }
226};
227
228hi_export template<typename CharT>
229struct std::formatter<hi::language_tag, CharT> : std::formatter<std::string_view, CharT> {
230 auto format(hi::language_tag const& t, auto& fc) const
231 {
232 return std::formatter<std::string_view, CharT>::format(to_string(t), fc);
233 }
234};
235
236// XXX C++23 should have this fixed?
237hi_export template<typename CharT>
238struct std::formatter<std::vector<hi::language_tag>, CharT> : std::formatter<std::string_view, CharT> {
239 auto format(std::vector<hi::language_tag> const& t, auto& fc) const
240 {
241 auto r = std::string{};
242 for (hilet language : t) {
243 if (not r.empty()) {
244 r += ", ";
245 }
246 r += std::format("{}", language);
247 }
248 return std::formatter<std::string_view, CharT>::format(r, fc);
249 }
250};
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
std::vector< language_tag > variants(std::vector< language_tag > languages)
Add variants to the list of languages.
Definition language_tag_impl.hpp:2069
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
ISO-15924 script code.
Definition iso_15924_intf.hpp:20
constexpr bool left_to_right() const noexcept
Is this script written left-to-right.
Definition iso_15924_impl.hpp:346
The IETF BCP 47 language tag.
Definition language_tag_intf.hpp:28
language_tag expand() const noexcept
Expand the language tag to include script and language.
Definition language_tag_impl.hpp:2035
bool empty() const noexcept
Check if the language tag is empty.
Definition language_tag_intf.hpp:70
generator< language_tag > canonical_variants() const noexcept
Get variants of the language_tag.
Definition language_tag_intf.hpp:109
bool left_to_right() const noexcept
The language direction for this language-tag.
Definition language_tag_intf.hpp:166
iso_15924 default_script() const noexcept
Get the default-script for this language.
Definition language_tag_intf.hpp:157
generator< language_tag > variants() const noexcept
Get variants of the language_tag.
Definition language_tag_intf.hpp:89
constexpr friend bool matches(language_tag const &lhs, language_tag const &rhs) noexcept
Check if two language_tags match for their non-empty fields.
Definition language_tag_intf.hpp:188
static language_tag parse(std::string_view str)
Parse the language, script and region raw from the string.
Definition language_tag_impl.hpp:1961
std::vector< language_tag > all_variants() const noexcept
Creates variants of a language tag, including those by expanding the normal variants.
Definition language_tag_intf.hpp:121
language_tag shrink() const noexcept
Get a tag with only the language.
Definition language_tag_intf.hpp:144
T find(T... args)
T operator()(T... args)
T to_string(T... args)