Blender  V3.3
boost_locale_wrapper.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2012 Blender Foundation. All rights reserved. */
3 
8 #include <boost/locale.hpp>
9 #include <iostream>
10 #include <stdio.h>
11 
12 #include "boost_locale_wrapper.h"
13 
14 static std::string messages_path;
15 static std::string default_domain;
16 static std::string locale_str;
17 
18 /* NOTE: We cannot use short stuff like `boost::locale::gettext`, because those return
19  * `std::basic_string` objects, which c_ptr()-returned char* is no more valid
20  * once deleted (which happens as soons they are out of scope of this func). */
21 typedef boost::locale::message_format<char> char_message_facet;
22 static std::locale locale_global;
24 
26 {
27  /* Cache facet in global variable. Not only is it better for performance,
28  * it also fixes crashes on macOS when doing translation from threads other
29  * than main. Likely because of some internal thread local variables. */
30  try {
31  /* facet_global reference is valid as long as local_global exists,
32  * so we store both. */
33  locale_global = std::locale();
34  facet_global = &std::use_facet<char_message_facet>(locale_global);
35  }
36  catch (const std::bad_cast
37  &e) { /* if std::has_facet<char_message_facet>(l) == false, LC_ALL = "C" case */
38 #ifndef NDEBUG
39  std::cout << "bl_locale_global_cache:" << e.what() << " \n";
40 #endif
41  (void)e;
43  }
44  catch (const std::exception &e) {
45 #ifndef NDEBUG
46  std::cout << "bl_locale_global_cache:" << e.what() << " \n";
47 #endif
48  (void)e;
50  }
51 }
52 
53 void bl_locale_init(const char *_messages_path, const char *_default_domain)
54 {
55  /* Avoid using ICU backend, we do not need its power and it's rather heavy! */
56  boost::locale::localization_backend_manager lman =
57  boost::locale::localization_backend_manager::global();
58 #if defined(_WIN32)
59  lman.select("winapi");
60 #else
61  lman.select("posix");
62 #endif
63  boost::locale::localization_backend_manager::global(lman);
64 
65  messages_path = _messages_path;
66  default_domain = _default_domain;
67 }
68 
69 void bl_locale_set(const char *locale)
70 {
71  boost::locale::generator gen;
72  std::locale _locale;
73  /* Specify location of dictionaries. */
74  gen.add_messages_path(messages_path);
75  gen.add_messages_domain(default_domain);
76  // gen.set_default_messages_domain(default_domain);
77 
78  try {
79  if (locale && locale[0]) {
80  _locale = gen(locale);
81  }
82  else {
83 #if defined(__APPLE__) && !defined(WITH_HEADLESS) && !defined(WITH_GHOST_SDL)
84  std::string locale_osx = osx_user_locale() + std::string(".UTF-8");
85  _locale = gen(locale_osx.c_str());
86 #else
87  _locale = gen("");
88 #endif
89  }
90  std::locale::global(_locale);
91  /* NOTE: boost always uses "C" LC_NUMERIC by default! */
92 
94 
95  /* Generate the locale string
96  * (useful to know which locale we are actually using in case of "default" one). */
97 #define LOCALE_INFO std::use_facet<boost::locale::info>(_locale)
98 
99  locale_str = LOCALE_INFO.language();
100  if (LOCALE_INFO.country() != "") {
101  locale_str += "_" + LOCALE_INFO.country();
102  }
103  if (LOCALE_INFO.variant() != "") {
104  locale_str += "@" + LOCALE_INFO.variant();
105  }
106 
107 #undef LOCALE_INFO
108  }
109  /* Extra catch on `std::runtime_error` is needed for macOS/Clang as it seems that exceptions
110  * like `boost::locale::conv::conversion_error` (which inherit from `std::runtime_error`) are
111  * not caught by their ancestor `std::exception`. See T88877#1177108 */
112  catch (std::runtime_error const &e) {
113  std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
114  }
115  catch (std::exception const &e) {
116  std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
117  }
118 }
119 
120 const char *bl_locale_get(void)
121 {
122  return locale_str.c_str();
123 }
124 
125 const char *bl_locale_pgettext(const char *msgctxt, const char *msgid)
126 {
127  if (facet_global) {
128  char const *r = facet_global->get(0, msgctxt, msgid);
129  if (r) {
130  return r;
131  }
132  }
133 
134  return msgid;
135 }
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static std::locale locale_global
static void bl_locale_global_cache()
static std::string messages_path
const char * bl_locale_pgettext(const char *msgctxt, const char *msgid)
static std::string locale_str
const char * bl_locale_get(void)
void bl_locale_set(const char *locale)
static char_message_facet const * facet_global
boost::locale::message_format< char > char_message_facet
void bl_locale_init(const char *_messages_path, const char *_default_domain)
static std::string default_domain
#define LOCALE_INFO
SyclQueue void void size_t num_bytes void
const char * osx_user_locale()