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 "../logger.hpp"
10#include "language_tag.hpp"
11#include <string>
12#include <vector>
13#include <functional>
14#include <mutex>
15
16namespace tt {
17
18
19struct language {
20 language_tag tag;
21 std::function<int(int)> plurality_func;
22
23 language(language_tag tag) noexcept;
24
25 language(language const &) = delete;
26 language(language &&) = delete;
27 language &operator=(language const &) = delete;
28 language &operator=(language &&) = delete;
29
30 [[nodiscard]] ssize_t plurality(long long n, ssize_t max) const noexcept {
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
42 inline static std::vector<language *> preferred_languages;
43 inline static std::recursive_mutex static_mutex;
44
45 [[nodiscard]] static language *find(language_tag const &tag) noexcept {
46 ttlet lock = std::scoped_lock(static_mutex);
47
48 ttlet i = languages.find(tag);
49 if (i != languages.end()) {
50 return i->second.get();
51 } else {
52 return nullptr;
53 }
54 }
55
56 [[nodiscard]] static language &find_or_create(language_tag const &tag) noexcept
57 {
58 ttlet lock = std::scoped_lock(static_mutex);
59
60 auto *r = find(tag);
61 if (!r) {
62 auto tmp = std::make_unique<language>(tag);
63 r = tmp.get();
64 languages[tag] = std::move(tmp);
65 }
66 return *r;
67 }
68
73 {
75
76 auto prev_short_tag = language_tag{};
77 for (ttlet &tag: tags) {
78 ttlet short_tag = tag.short_tag();
79
80 if (prev_short_tag && short_tag != prev_short_tag) {
81 if (std::find(r.cbegin(), r.cend(), prev_short_tag) == r.cend()) {
82 r.push_back(prev_short_tag);
83 }
84 }
85
86 if (std::find(r.cbegin(), r.cend(), tag) == r.cend()) {
87 r.push_back(tag);
88 }
89
90 prev_short_tag = short_tag;
91 }
92
93 if (prev_short_tag) {
94 if (std::find(r.cbegin(), r.cend(), prev_short_tag) == r.cend()) {
95 r.push_back(prev_short_tag);
96 }
97 }
98 return r;
99 }
100
101 static void set_preferred_languages(std::vector<language_tag> tags) noexcept
102 {
103 ttlet lock = std::scoped_lock(static_mutex);
104
105 auto tmp = std::vector<language*>{};
106 for (ttlet &tag: add_short_names(tags)) {
107 tmp.push_back(&find_or_create(tag));
108 }
109
110 if (compare_then_assign(preferred_languages, tmp)) {
111 auto language_order_string = std::string{};
112 for (ttlet &language : tmp) {
113 if (language_order_string.size() != 0) {
114 language_order_string += ", ";
115 }
116 language_order_string += to_string(language->tag);
117 }
118 tt_log_info("Setting preferred language in order: ", language_order_string);
119 }
120 }
121
126};
127
128}
Definition language.hpp:19
static std::vector< language_tag > add_short_names(std::vector< language_tag > tags) noexcept
Add short language names to the list of names.
Definition language.hpp:72
static std::vector< language_tag > read_os_preferred_languages() noexcept
Get the preferred language tags from the operating system.
An IETF BCP 47 Language tag.
Definition language_tag.hpp:15
T cbegin(T... args)
T end(T... args)
T find(T... args)
T move(T... args)
T push_back(T... args)
T to_string(T... args)