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