HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
language.hpp
1// Copyright Take Vos 2020-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 "../cast.hpp"
8#include "../i18n/language_tag.hpp"
9#include <string>
10#include <vector>
11#include <functional>
12#include <mutex>
13#include <format>
14
15namespace hi::inline v1 {
16
17class language {
18public:
19 language_tag tag;
20 std::function<int(int)> plurality_func;
21
22 language(language_tag tag) noexcept;
23 language(language const &) = delete;
24 language(language &&) = delete;
25 language &operator=(language const &) = delete;
26 language &operator=(language &&) = delete;
27
28 [[nodiscard]] ssize_t plurality(long long n, ssize_t max) const noexcept
29 {
30 auto r = 0;
31 if (plurality_func) {
32 r = plurality_func(narrow_cast<int>(n % 1'000'000));
33 } else {
34 // Use English as fallback.
35 r = static_cast<int>(n == 1);
36 }
37 return std::clamp(narrow_cast<ssize_t>(r), ssize_t{0}, max - 1);
38 }
39
40 [[nodiscard]] static language *find(language_tag const &tag) noexcept
41 {
42 hilet lock = std::scoped_lock(_mutex);
43
44 hilet i = _languages.find(tag);
45 if (i != _languages.end()) {
46 return i->second.get();
47 } else {
48 return nullptr;
49 }
50 }
51
52 [[nodiscard]] static language &find_or_create(language_tag const &tag) noexcept
53 {
54 hilet lock = std::scoped_lock(_mutex);
55
56 auto *r = find(tag);
57 if (!r) {
58 auto tmp = std::make_unique<language>(tag);
59 r = tmp.get();
60 _languages[tag] = std::move(tmp);
61 }
62 return *r;
63 }
64
65 [[nodiscard]] static std::vector<language *> make_languages(std::vector<language_tag> tags) noexcept
66 {
67 hilet lock = std::scoped_lock(_mutex);
68
69 auto variant_tags = variants(tags);
70 auto r = std::vector<language *>{};
71 r.reserve(variant_tags.size());
72
73 for (hilet &tag: variant_tags) {
74 r.push_back(&find_or_create(tag));
75 }
76
77 return r;
78 }
79
80private:
81 inline static std::atomic<bool> _is_running;
83 inline static std::recursive_mutex _mutex;
84};
85
86} // namespace hi::inline v1
87
88template<typename CharT>
89struct std::formatter<std::vector<hi::language *>, CharT> : std::formatter<std::string_view, CharT> {
90 auto format(std::vector<hi::language *> const &t, auto &fc)
91 {
92 auto r = std::string{};
93 for (hilet language : t) {
94 if (not r.empty()) {
95 r += ", ";
96 }
97 r += language->tag.to_string();
98 }
99 return std::formatter<std::string_view, CharT>::format(r, fc);
100 }
101};
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
std::vector< language_tag > variants(std::vector< language_tag > languages)
Add variants to the list of languages.
Definition language.hpp:17
The IETF BCP 47 language tag.
Definition language_tag.hpp:25
T move(T... args)
T reserve(T... args)