Refactor: Move translation handling fully into blentranslation

No need to have the extra abstraction, simpler to have it together
in the same module.

Pull Request: https://projects.blender.org/blender/blender/pulls/133347
This commit is contained in:
Brecht Van Lommel
2024-12-14 17:33:02 +01:00
parent 860bfd786e
commit 139f0d8c32
10 changed files with 70 additions and 188 deletions

View File

@@ -35,10 +35,6 @@ if(WITH_CYCLES)
add_subdirectory(cycles)
endif()
if(WITH_INTERNATIONAL)
add_subdirectory(locale)
endif()
if(WITH_BULLET)
add_subdirectory(rigidbody)
endif()

View File

@@ -1,40 +0,0 @@
# SPDX-FileCopyrightText: 2012 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
.
)
set(INC_SYS
)
set(SRC
blender_locale.cpp
messages.cpp
blender_locale.h
messages.h
)
set(LIB
PRIVATE bf::blenlib
PRIVATE bf::intern::guardedalloc
)
if(APPLE)
# Cocoa code to read the locale on OSX
list(APPEND SRC
messages_apple.mm
)
endif()
if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
endif()
if(WITH_GHOST_SDL)
add_definitions(-DWITH_GHOST_SDL)
endif()
blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -1,48 +0,0 @@
/* SPDX-FileCopyrightText: 2012 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_locale
*/
#include "blender_locale.h"
#include "messages.h"
static std::string messages_path;
static std::string default_domain;
static std::string locale_str;
void bl_locale_init(const char *_messages_path, const char *_default_domain)
{
messages_path = _messages_path;
default_domain = _default_domain;
}
void bl_locale_free()
{
blender::locale::free();
}
void bl_locale_set(const char *locale_name)
{
/* Get locale name from system if not specified. */
std::string locale_full_name = locale_name ? locale_name : "";
/* Initialize and load .mo file for locale. */
blender::locale::init(locale_full_name, {default_domain}, {messages_path});
/* Generate the locale string, to known which one is used in case of default locale. */
locale_str = blender::locale::full_name();
}
const char *bl_locale_get(void)
{
return locale_str.c_str();
}
const char *bl_locale_pgettext(const char *msgctxt, const char *msgid)
{
const char *r = blender::locale::translate(0, msgctxt, msgid);
return (r) ? r : msgid;
}

View File

@@ -1,31 +0,0 @@
/* SPDX-FileCopyrightText: 2012 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_locale
* A thin C wrapper around `boost::locale`.
*/
#ifndef __BOOST_LOCALE_WRAPPER_H__
#define __BOOST_LOCALE_WRAPPER_H__
#ifdef __cplusplus
extern "C" {
#endif
void bl_locale_init(const char *messages_path, const char *default_domain);
void bl_locale_set(const char *locale);
void bl_locale_free(void);
const char *bl_locale_get(void);
const char *bl_locale_pgettext(const char *msgctxt, const char *msgid);
#if defined(__APPLE__) && !defined(WITH_HEADLESS) && !defined(WITH_GHOST_SDL)
const char *osx_user_locale(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __BOOST_LOCALE_WRAPPER_H__ */

View File

@@ -19,19 +19,30 @@ set(SRC
BLT_translation.hh
)
if(WITH_INTERNATIONAL)
list(APPEND SRC
intern/messages.cc
intern/messages.hh
)
if(APPLE)
list(APPEND SRC
intern/messages_apple.mm
)
endif()
endif()
set(LIB
PRIVATE bf::blenkernel
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::imbuf
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
)
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
list(APPEND LIB
bf_intern_locale
)
endif()
if(WITH_PYTHON)

View File

@@ -11,6 +11,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#ifndef _WIN32
# include <clocale>
@@ -27,8 +28,6 @@
#include "BKE_appdir.hh"
#include "IMB_thumbs.hh"
#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
@@ -38,7 +37,11 @@
# include "BLI_fileops.h"
# include "BLI_linklist.h"
# include "blender_locale.h"
# include "CLG_log.h"
# include "messages.hh"
static CLG_LogRef LOG = {"translation.language"};
/* Locale options. */
static const char **locales = nullptr;
@@ -66,17 +69,19 @@ static void free_locales()
static void fill_locales()
{
std::optional<std::string> languages_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
char languages[FILE_MAX];
LinkNode *lines = nullptr, *line = nullptr;
char *str;
int idx = 0;
if (!languages_path.has_value()) {
CLOG_WARN(&LOG, "'locale' data path for translations not found");
return;
}
free_locales();
if (languages_path.has_value()) {
BLI_path_join(languages, FILE_MAX, languages_path->c_str(), "languages");
line = lines = BLI_file_read_as_lines(languages);
}
char languages[FILE_MAX];
BLI_path_join(languages, FILE_MAX, languages_path->c_str(), "languages");
LinkNode *lines = BLI_file_read_as_lines(languages);
LinkNode *line = lines;
int idx = 0;
/* This whole "parsing" code is a bit weak, in that it expects strictly formatted input file...
* Should not be a problem, though, as this file is script-generated! */
@@ -84,7 +89,7 @@ static void fill_locales()
/* First loop to find highest locale ID */
while (line) {
int t;
str = (char *)line->link;
char *str = (char *)line->link;
if (ELEM(str[0], '#', '\0')) {
line = line->next;
continue; /* Comment or void... */
@@ -109,7 +114,7 @@ static void fill_locales()
while (line) {
const char *loc, *sep1, *sep2, *sep3;
str = (char *)line->link;
char *str = (char *)line->link;
if (ELEM(str[0], '#', '\0')) {
line = line->next;
continue;
@@ -181,10 +186,6 @@ const EnumPropertyItem *BLT_lang_RNA_enum_properties()
void BLT_lang_init()
{
#ifdef WITH_INTERNATIONAL
const std::optional<std::string> messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
#endif
/* Make sure LANG is correct and wouldn't cause #std::runtime_error. */
#ifndef _WIN32
/* TODO(sergey): This code only ensures LANG is set properly, so later when
@@ -205,7 +206,7 @@ void BLT_lang_init()
old_locale = BLI_strdup(old_locale);
if (setlocale(LC_ALL, lang) == nullptr) {
setenv("LANG", "C", 1);
printf("Warning: Falling back to the standard locale (\"C\")\n");
CLOG_WARN(&LOG, "Falling back to standard locale (\"C\")");
}
setlocale(LC_ALL, old_locale);
MEM_freeN(old_locale);
@@ -213,21 +214,14 @@ void BLT_lang_init()
#endif
#ifdef WITH_INTERNATIONAL
if (messagepath.has_value()) {
bl_locale_init(messagepath->c_str(), TEXT_DOMAIN_NAME);
fill_locales();
}
else {
printf("%s: 'locale' data path for translations not found, continuing\n", __func__);
}
#else
fill_locales();
#endif
}
void BLT_lang_free()
{
#ifdef WITH_INTERNATIONAL
bl_locale_free();
blender::locale::free();
free_locales();
#endif
}
@@ -252,27 +246,12 @@ void BLT_lang_set(const char *str)
{
#ifdef WITH_INTERNATIONAL
int ulang = ULANGUAGE;
const char *short_locale = str ? str : LOCALE(ulang);
const char *short_locale_utf8 = nullptr;
std::string locale_name = str ? str : LOCALE(ulang);
/* blender::locale assumes UTF-8, no need to put it in the name. */
const std::optional<std::string> messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
blender::locale::init(locale_name, {TEXT_DOMAIN_NAME}, {messagepath.value_or("")});
/* We want to avoid locales like '.UTF-8'! */
if (short_locale[0]) {
/* Hooray! Encoding needs to be placed *before* variant! */
const char *variant = strchr(short_locale, '@');
if (variant) {
char *locale = BLI_strdupn(short_locale, variant - short_locale);
short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant);
MEM_freeN(locale);
}
else {
short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
}
bl_locale_set(short_locale_utf8);
MEM_freeN((void *)short_locale_utf8);
}
else {
bl_locale_set(short_locale);
}
#else
(void)str;
#endif
@@ -285,7 +264,7 @@ const char *BLT_lang_get()
const char *locale = LOCALE(ULANGUAGE);
if (locale[0] == '\0') {
/* Default locale, we have to find which one we are actually using! */
locale = bl_locale_get();
locale = blender::locale::full_name();
}
return locale;
}

View File

@@ -14,8 +14,6 @@
#include "BLT_translation.hh"
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h" /* For user settings. */
#ifdef WITH_PYTHON
@@ -24,7 +22,7 @@
#ifdef WITH_INTERNATIONAL
# include "BLI_threads.h"
# include "blender_locale.h"
# include "messages.hh"
#endif /* WITH_INTERNATIONAL */
bool BLT_is_default_context(const char *msgctxt)
@@ -45,15 +43,17 @@ const char *BLT_pgettext(const char *msgctxt, const char *msgid)
if (BLT_is_default_context(msgctxt)) {
msgctxt = BLT_I18NCONTEXT_DEFAULT;
}
ret = bl_locale_pgettext(msgctxt, msgid);
/* We assume if the returned string is the same (memory level) as the msgid,
* no translation was found, and we can try py scripts' ones!
*/
ret = blender::locale::translate(0, msgctxt, msgid);
/* No translation found? Try py script translations. */
if (ret == nullptr) {
# ifdef WITH_PYTHON
if (ret == msgid) {
ret = BPY_app_translations_py_pgettext(msgctxt, msgid);
}
# else
ret = msgid;
# endif
}
}
return ret;

View File

@@ -5,7 +5,11 @@
*
* Adapted from boost::locale */
#include "messages.h"
/** \file
* \ingroup blt
*/
#include "messages.hh"
#include <algorithm>
#include <cstdint>
@@ -26,8 +30,12 @@
# include "BLI_winstuff.h"
#endif
#include "CLG_log.h"
namespace blender::locale {
static CLG_LogRef LOG = {"translation.messages"};
/* Upper/lower case, intentionally restricted to ASCII. */
static constexpr bool is_upper_ascii(const char c)
@@ -556,8 +564,11 @@ void init(const StringRef locale_full_name,
global_messages = std::make_unique<MOMessages>(info, domains, paths);
global_full_name = info.to_full_name();
if (!global_messages->error().empty()) {
printf("bl_locale_set(%s): %s\n", global_full_name.c_str(), global_messages->error().c_str());
if (global_messages->error().empty()) {
CLOG_INFO(&LOG, 2, "Locale %s used for translation", global_full_name.c_str());
}
else {
CLOG_ERROR(&LOG, "Locale %s: %s", global_full_name.c_str(), global_messages->error().c_str());
free();
}
}

View File

@@ -3,6 +3,10 @@
*
* Adapted from boost::locale */
/** \file
* \ingroup blt
*/
#include <string>
#include "BLI_string_ref.hh"

View File

@@ -3,10 +3,10 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup intern_locale
* \ingroup blt
*/
#include "messages.h"
#include "messages.hh"
#import <Cocoa/Cocoa.h>