FlightGear next
TranslationUnit.cxx
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Florent Rougon
2// SPDX-License-Identifier: GPL-2.0-or-later
3
8
9#include <cassert>
10#include <cstddef>
11#include <memory>
12#include <string>
13#include <utility>
14#include <vector>
15
16#include <simgear/debug/logstream.hxx>
17#include <simgear/nasal/cppbind/Ghost.hxx>
18#include <simgear/nasal/cppbind/NasalCallContext.hxx>
19
20#include <Main/locale.hxx>
21#include <Main/globals.hxx>
22
23#include "TranslationUnit.hxx"
24
26
27TranslationUnit::TranslationUnit(const std::string sourceText,
28 const std::vector<std::string> targetTexts,
29 bool hasPlural)
30 : _sourceText(std::move(sourceText)),
31 _targetTexts(std::move(targetTexts)),
32 _hasPlural(hasPlural)
33{ }
34
36{
37 return _sourceText;
38}
39
40void TranslationUnit::setSourceText(std::string text)
41{
42 _sourceText = std::move(text);
43}
44
45std::string TranslationUnit::getTargetText(int pluralFormIndex) const
46{
47 if (static_cast<std::size_t>(pluralFormIndex) >= _targetTexts.size()) {
48 return {};
49 }
50
51 return _targetTexts[pluralFormIndex];
52}
53
55{
56 return _targetTexts.size();
57}
58
59void TranslationUnit::setTargetText(int pluralFormIndex, std::string text)
60{
61 if (static_cast<std::size_t>(pluralFormIndex) >= _targetTexts.size()) {
62 _targetTexts.resize(pluralFormIndex + 1);
63 }
64
65 _targetTexts[pluralFormIndex] = std::move(text);
66}
67
68void TranslationUnit::setTargetTexts(std::vector<std::string> texts)
69{
70 _targetTexts = std::move(texts);
71}
72
74{
75 return _hasPlural;
76}
77
79{
80 _hasPlural = hasPlural;
81}
82
84{
85 const std::size_t nbTargetTexts = getNumberOfTargetTexts();
86 std::string res; // empty result by default
87
88 if (nbTargetTexts == 0) { // e.g., in the default translation
89 res = getSourceText();
90 } else {
91 res = getTargetText(0);
92
93 if (res.empty()) { // not translated
94 res = getSourceText();
95 }
96 }
97
98 return res;
99}
100
101std::string TranslationUnit::getTranslation(intType cardinalNumber) const
102{
103 if (!getPluralStatus()) {
104 SG_LOG(SG_GENERAL, SG_WARN,
105 "TranslationUnit::getTranslation(intType cardinalNumber) called "
106 "for “" << getSourceText() << "”), however this string wasn't "
107 "declared with has-plural=\"true\" in the default translation");
108 return getSourceText();
109 }
110
111 const std::size_t nbTargetTexts = getNumberOfTargetTexts();
112 if (nbTargetTexts == 0) { // e.g., in the default translation
113 return getSourceText();
114 }
115
116 const std::string languageId = globals->get_locale()->getLanguageId();
117 const std::size_t pluralFormIndex =
118 LanguageInfo::getPluralFormIndex(languageId, cardinalNumber);
119 assert(pluralFormIndex < nbTargetTexts);
120
121 std::string res = getTargetText(pluralFormIndex);
122
123 if (res.empty()) { // not translated
124 res = getSourceText();
125 }
126
127 return res;
128}
129
130static naRef f_getTranslation(const TranslationUnit& translUnit,
131 nasal::CallContext ctx)
132{
133 using intType = LanguageInfo::intType;
134 intType cardinalNumber;
135
136 switch (ctx.argc) {
137 case 0:
138 if (translUnit.getPluralStatus()) {
139 ctx.runtimeError(
140 "TranslationUnit has plural status 1, therefore its "
141 "getTranslation() method requires an argument");
142 }
143 return ctx.to_nasal(translUnit.getTranslation());
144 case 1:
145 if (!translUnit.getPluralStatus()) {
146 ctx.runtimeError(
147 "TranslationUnit has plural status 0, therefore its "
148 "getTranslation() method must be called with no argument");
149 }
150 cardinalNumber = ctx.requireArg<intType>(0);
151 return ctx.to_nasal(translUnit.getTranslation(cardinalNumber));
152 default:
153 ctx.runtimeError(
154 "TranslationUnit.getTranslation() or "
155 "TranslationUnit.getTranslation(cardinalNumber)");
156 }
157
158 return {}; // unreachable
159}
160
161static naRef f_getTargetText(const TranslationUnit& translUnit,
162 nasal::CallContext ctx)
163{
164 if (ctx.argc > 1) {
165 ctx.runtimeError("TranslationUnit.getTargetText([index])");
166 }
167
168 const auto index = ctx.getArg<std::size_t>(0); // the index defaults to 0
169
170 if (translUnit.getNumberOfTargetTexts() == 0) {
171 ctx.runtimeError(
172 "cannot call getTargetText() on a TranslationUnit that has "
173 "no target texts");
174 } else if (index >= translUnit.getNumberOfTargetTexts()) {
175 ctx.runtimeError(
176 "invalid target text index %d: TranslationUnit only has %d "
177 "target texts", index, translUnit.getNumberOfTargetTexts());
178 }
179
180 return ctx.to_nasal(translUnit.getTargetText(index));
181}
182
183// Static member function
185{
186 using TranslationUnitRef = std::shared_ptr<TranslationUnit>;
187 using NasalTranslationUnit = nasal::Ghost<TranslationUnitRef>;
188
189 NasalTranslationUnit::init("TranslationUnit")
190 .member("sourceText", &TranslationUnit::getSourceText)
191 .member("pluralStatus", &TranslationUnit::getPluralStatus)
192 .member("nbTargetTexts", &TranslationUnit::getNumberOfTargetTexts)
193 .method("getTargetText", &f_getTargetText)
194 .method("getTranslation", &f_getTranslation);
195}
static naRef f_getTranslation(const TranslationUnit &translUnit, nasal::CallContext ctx)
static naRef f_getTargetText(const TranslationUnit &translUnit, nasal::CallContext ctx)
Container class for a string and its translation.
static std::size_t getPluralFormIndex(const std::string &languageId, intType number)
Return the index of the plural form to use for a number of “items”
long long intType
Class holding a source string and its translation in a language.
std::string getTargetText(int pluralFormIndex=0) const
Get the target text (translated string) associated to pluralFormIndex.
std::string getTranslation() const
Get the target text of a non-plural translation unit.
bool getPluralStatus() const
Return the plural status of a translation unit.
std::size_t getNumberOfTargetTexts() const
Return the number of target texts (plural forms) present in the object.
std::string getSourceText() const
Return the source text of the object, i.e. the “engineering English” form.
TranslationUnit(const std::string sourceText={}, const std::vector< std::string > targetTexts={}, bool hasPlural=false)
void setPluralStatus(int hasPlural)
Set the plural status of a translation unit.
void setTargetTexts(std::vector< std::string > texts)
Set all target texts at once.
void setSourceText(std::string text)
Set the source text of the object, i.e. the “engineering English” form.
static void setupGhost()
Set up a Nasal type that wraps TranslationUnit.
void setTargetText(int pluralFormIndex, std::string text)
Set the target text for the specified plural form.
flightgear::LanguageInfo::intType intType
Class providing information on plural forms.
FGGlobals * globals
Definition globals.cxx:142
FlightGear Localization Support.