20#include <boost/version.hpp>
21#if BOOST_VERSION < 106700
25#include <config_libcxx.h>
27#define _LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR
29#define _HAS_AUTO_PTR_ETC 1
39#if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined EMSCRIPTEN
45#include <osl/thread.h>
46#include <osl/file.hxx>
48#include <rtl/bootstrap.hxx>
51#include <boost/locale.hpp>
52#include <boost/locale/gnu_gettext.hpp>
54#include <unordered_map>
57#include <osl/detail/android-bootstrap.h>
61#include <osl/detail/emscripten-bootstrap.h>
64#if defined(_WIN32) && defined(DBG_UTIL)
73 OUString createFromUtf8(
const char* data,
size_t size)
76 bool bSuccess = rtl_convertStringToUString(&aTarget.pData,
79 RTL_TEXTENCODING_UTF8,
80 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR);
86 OString genKeyId(
const OString& rGenerator)
88 sal_uInt32 nCRC = rtl_crc32(0, rGenerator.getStr(), rGenerator.getLength());
90 static const char sSymbols[] =
91 "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";
93 for (
short nKeyInd = 0; nKeyInd < 5; ++nKeyInd)
95 sKeyId[nKeyInd] = sSymbols[(nCRC & 63) % strlen(sSymbols)];
103#if defined(_WIN32) && defined(DBG_UTIL)
104static int IgnoringCrtReportHook(
int reportType,
wchar_t *message,
int * )
107 if (reportType == _CRT_WARN)
109 else if (reportType == _CRT_ERROR)
111 else if (reportType == _CRT_ASSERT)
114 sType =
"?(" + OUString::number(reportType) +
")";
116 SAL_WARN(
"unotools.i18n",
"CRT Report Hook: " << sType <<
": " << OUString(o3tl::toU(message)));
127 static std::unordered_map<OString, std::locale> aCache;
129 OString sUnique = sIdentifier + aPrefixName;
130 auto aFind = aCache.find(sUnique);
131 if (aFind != aCache.end())
132 return aFind->second;
133 boost::locale::generator gen;
134#if BOOST_VERSION < 108100
135 gen.characters(boost::locale::char_facet);
136 gen.categories(boost::locale::message_facet | boost::locale::information_facet);
138 gen.characters(boost::locale::char_facet_t::char_f);
139 gen.categories(boost::locale::category_t::message | boost::locale::category_t::information);
141#if defined(ANDROID) || defined(EMSCRIPTEN)
142 OString sPath(OString(lo_get_app_data_dir()) +
"/program/resource");
144 OUString uri(
"$BRAND_BASE_DIR/$BRAND_SHARE_RESOURCE_SUBDIR/");
145 rtl::Bootstrap::expandMacros(uri);
147 osl::File::getSystemPathFromFileURL(uri, path);
151 constexpr rtl_TextEncoding eEncoding = RTL_TEXTENCODING_UTF8;
153 const rtl_TextEncoding eEncoding = osl_getThreadTextEncoding();
157 gen.add_messages_path(std::string(sPath));
158#if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined EMSCRIPTEN
160 bindtextdomain(aPrefixName.data(), sPath.getStr());
162 bind_textdomain_codeset(aPrefixName.data(),
"UTF-8");
164 gen.add_messages_domain(aPrefixName.data());
166#if defined(_WIN32) && defined(DBG_UTIL)
187 struct CrtSetReportHook
189 int mnCrtSetReportHookSucceeded;
193 mnCrtSetReportHookSucceeded = _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, IgnoringCrtReportHook);
198 if (mnCrtSetReportHookSucceeded >= 0)
199 _CrtSetReportHookW2(_CRT_RPTHOOK_REMOVE, IgnoringCrtReportHook);
205 std::locale aRet(gen(std::string(sIdentifier)));
207 aCache[sUnique] = aRet;
213 assert(!strchr(sContextAndId.
mpId,
'\004') &&
"should be using nget, not get");
216 if (std::use_facet<boost::locale::info>(loc).language() ==
"qtz")
218 OString sKeyId(genKeyId(OString::Concat(sContextAndId.
mpContext) +
"|" + std::string_view(sContextAndId.
mpId)));
219 return OUString::fromUtf8(sKeyId) +
u"\u2016" + createFromUtf8(sContextAndId.
mpId, strlen(sContextAndId.
mpId));
223 const std::string ret = boost::locale::pgettext(sContextAndId.
mpContext, sContextAndId.
mpId, loc);
229 if (std::use_facet<boost::locale::info>(loc).country() ==
"CH" &&
230 std::use_facet<boost::locale::info>(loc).language() ==
"de")
231 result =
result.replaceAll(OUString::fromUtf8(
"\xC3\x9F"),
"ss");
239 if (std::use_facet<boost::locale::info>(loc).language() ==
"qtz")
241 OString sKeyId(genKeyId(OString::Concat(aContextSingularPlural.
mpContext) +
"|" + aContextSingularPlural.
mpSingular));
242 const char* pForm =
n == 0 ? aContextSingularPlural.
mpSingular : aContextSingularPlural.
mpPlural;
243 return OUString::fromUtf8(sKeyId) +
u"\u2016" + createFromUtf8(pForm, strlen(pForm));
247 const std::string ret = boost::locale::npgettext(aContextSingularPlural.
mpContext, aContextSingularPlural.
mpSingular, aContextSingularPlural.
mpPlural,
n, loc);
252 if (std::use_facet<boost::locale::info>(loc).country() ==
"CH" &&
253 std::use_facet<boost::locale::info>(loc).language() ==
"de")
254 result =
result.replaceAll(OUString::fromUtf8(
"\xC3\x9F"),
"ss");
289 if (
mpId ==
nullptr || other.
mpId ==
nullptr)
293 return strcmp(
mpId,other.
mpId) == 0;
OUString getGlibcLocaleString(std::u16string_view rEncoding) const
#define SAL_WARN(area, stream)
OUString nget(TranslateNId aContextSingularPlural, int n, const std::locale &loc)
static ResHookProc pImplResHookProc
ResHookProc GetReadStringHook()
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString ExpandVariables(const OUString &rString)
OUString get(TranslateId sContextAndId, const std::locale &loc)
void SetReadStringHook(ResHookProc pProc)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OUString(* ResHookProc)(const OUString &rStr)
bool operator==(const TranslateId &other) const
bool operator==(const TranslateNId &other) const