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