HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
language.hpp
1// Copyright 2020 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/observable.hpp"
7#include "TTauri/Foundation/numeric_cast.hpp"
8#include <string>
9#include <vector>
10#include <functional>
11#include <mutex>
12
13namespace tt {
14
15struct language {
16 std::string tag;
17 std::function<int(int)> plurality_func;
18
19 language(std::string tag) noexcept;
20
21 language(language const &) = delete;
22 language(language &&) = delete;
23 language &operator=(language const &) = delete;
24 language &operator=(language &&) = delete;
25
26 [[nodiscard]] ssize_t plurality(long long n, ssize_t max) const noexcept {
27 int r;
28 if (plurality_func) {
29 r = plurality_func(numeric_cast<int>(n % 1'000'000));
30 } else {
31 // Use English as fallback.
32 r = static_cast<int>(n == 1);
33 }
34 return std::clamp(numeric_cast<ssize_t>(r), ssize_t{0}, max - 1);
35 }
36
38 inline static observable<std::vector<language *>> preferred_languages;
39 inline static std::recursive_mutex static_mutex;
40
41 [[nodiscard]] static language *find(std::string const &tag) noexcept {
42 ttlet lock = std::scoped_lock(static_mutex);
43
44 ttlet 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(std::string const &tag) noexcept {
53 ttlet lock = std::scoped_lock(static_mutex);
54
55 auto *r = find(tag);
56 if (!r) {
57 auto tmp = std::make_unique<language>(tag);
58 r = tmp.get();
59 languages[tag] = std::move(tmp);
60 }
61 return *r;
62 }
63
69
70 std::string prev_short_tag;
71 for (ttlet &tag: tags) {
72 ttlet short_tag = split(tag, "-").front();
73
74 if (ssize(prev_short_tag) != 0 && short_tag != prev_short_tag) {
75 if (std::find(r.cbegin(), r.cend(), prev_short_tag) == r.cend()) {
76 r.push_back(prev_short_tag);
77 }
78 }
79
80 if (std::find(r.cbegin(), r.cend(), tag) == r.cend()) {
81 r.push_back(tag);
82 }
83
84 prev_short_tag = short_tag;
85 }
86
87 if (ssize(prev_short_tag) != 0) {
88 if (std::find(r.cbegin(), r.cend(), prev_short_tag) == r.cend()) {
89 r.push_back(prev_short_tag);
90 }
91 }
92 return r;
93 }
94
95 static void set_preferred_languages(std::vector<std::string> tags) noexcept {
96 ttlet lock = std::scoped_lock(static_mutex);
97
98 auto tmp = std::vector<language*>{};
99 for (ttlet &tag: add_short_names(tags)) {
100 tmp.push_back(&find_or_create(tag));
101 }
102
103 preferred_languages = tmp;
104 }
105
110};
111
112}
Definition observable.hpp:20
Definition language.hpp:15
static std::vector< std::string > get_preferred_language_tags() noexcept
Get the preferred language tags from the operating system.
static std::vector< std::string > add_short_names(std::vector< std::string > tags) noexcept
Add short language names to the list of names.
Definition language.hpp:67
T cbegin(T... args)
T end(T... args)
T find(T... args)
T move(T... args)
T push_back(T... args)