HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
translation.hpp
1// Copyright Take Vos 2020-2021.
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 "translation.hpp"
8#include "po_parser.hpp"
9#include "../i18n/i18n.hpp"
10#include "../formula/formula.hpp"
11#include "../utility/utility.hpp"
12#include "../settings/settings.hpp"
13#include "../unicode/unicode.hpp"
14#include "../telemetry/telemetry.hpp"
15#include "../macros.hpp"
16#include <string>
17#include <string_view>
18#include <vector>
19#include <unordered_map>
20#include <tuple>
21
22hi_export_module(hikogui.l10n.translation);
23
24namespace hi {
25inline namespace v1 {
26
28 std::string msgid;
29 language_tag language;
30
31 [[nodiscard]] std::size_t hash() const noexcept
32 {
33 return hash_mix(msgid, language);
34 }
35
36 [[nodiscard]] constexpr friend bool operator==(translation_key const &, translation_key const &) noexcept = default;
37};
38
39}} // namespace hi::inline v1
40
41template<>
42struct std::hash<hi::translation_key> {
43 [[nodiscard]] std::size_t operator()(hi::translation_key const &rhs) const noexcept
44 {
45 return rhs.hash();
46 }
47};
48
49namespace hi {
50inline namespace v1 {
51
53inline std::atomic<bool> translations_loaded = false;
54
55inline void add_translation(std::string_view msgid, language_tag language, std::vector<std::string> const &plural_forms) noexcept
56{
57 auto key = translation_key{std::string{msgid}, language};
58 translations[key] = plural_forms;
59}
60
61inline void add_translations(po_translations const &po_translations) noexcept
62{
63 for (hilet &translation : po_translations.translations) {
64 auto msgid = translation.msgctxt ? *translation.msgctxt + '|' + translation.msgid : translation.msgid;
65 add_translation(std::move(msgid), po_translations.language, translation.msgstr);
66 }
67}
68
69inline void load_translations(std::filesystem::path path)
70{
71 hi_log_info("Loading translation file {}.", path.string());
72 return add_translations(parse_po(path));
73}
74
75inline void load_translations()
76{
77 if (not translations_loaded.exchange(true)) {
78 // XXX Waiting for C++23 to extend life-time of temporaries in for loops.
80 for (auto &path : glob(resource_paths, "**/*.po")) {
81 try {
82 load_translations(path);
83 } catch (std::exception const &e) {
84 hi_log_error("Could not load translation file. {}", e.what());
85 }
86 }
87 }
88}
89
91get_translation(std::string_view msgid, long long n, std::vector<language_tag> const &languages) noexcept
92{
93 load_translations();
94
95 // Update only the language in each iteration.
96 auto key = translation_key{std::string{msgid}, language_tag{}};
97
98 for (hilet language : languages) {
99 key.language = language;
100
101 hilet i = translations.find(key);
102 if (i != translations.cend()) {
103 hilet plurality = cardinal_plural(language, n, i->second.size());
104 hilet &translation = i->second[plurality];
105 if (translation.size() != 0) {
106 return {translation, language};
107 }
108 }
109 }
110 hi_log_debug("No translation found for '{}'", msgid);
111 return {msgid, language_tag{"en-Latn-US"}};
112}
113
114
115}} // namespace hi::inline v1
hi_export generator< std::filesystem::path > glob(glob_pattern pattern) noexcept
Find paths on the filesystem that match the glob pattern.
Definition glob.hpp:879
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
hi_export generator< std::filesystem::path > resource_dirs() noexcept
The directories to search for resource files.
constexpr plurality cardinal_plural(language_tag language, std::integral auto n) noexcept
Get plural information of a number in a given language.
Definition unicode_plural.hpp:927
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
The IETF BCP 47 language tag.
Definition language_tag_intf.hpp:28
Definition translation.hpp:27
T exchange(T... args)
T move(T... args)
T operator()(T... args)
T what(T... args)