Host: Add disambiguation variants for translations

This commit is contained in:
Stenzek
2024-09-03 21:39:00 +10:00
parent 060c5553c0
commit a7d8e6d018
13 changed files with 312 additions and 237 deletions

View File

@ -210,10 +210,10 @@ static constexpr const std::array s_backend_names = {
#endif
};
static constexpr const std::array s_backend_display_names = {
TRANSLATE_NOOP("AudioStream", "Null (No Output)"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Null (No Output)", "AudioBackend"),
#ifndef __ANDROID__
TRANSLATE_NOOP("AudioStream", "Cubeb"),
TRANSLATE_NOOP("AudioStream", "SDL"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Cubeb", "AudioBackend"),
TRANSLATE_DISAMBIG_NOOP("Settings", "SDL", "AudioBackend"),
#else
"AAudio",
"OpenSL ES",
@ -250,26 +250,28 @@ static constexpr const std::array s_stretch_mode_names = {
"TimeStretch",
};
static constexpr const std::array s_stretch_mode_display_names = {
TRANSLATE_NOOP("AudioStream", "Off (Noisy)"),
TRANSLATE_NOOP("AudioStream", "Resampling (Pitch Shift)"),
TRANSLATE_NOOP("AudioStream", "Time Stretch (Tempo Change, Best Sound)"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Off (Noisy)", "AudioStretchMode"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Resampling (Pitch Shift)", "AudioStretchMode"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Time Stretch (Tempo Change, Best Sound)", "AudioStretchMode"),
};
const char* AudioStream::GetStretchModeName(AudioStretchMode mode)
{
return (static_cast<u32>(mode) < s_stretch_mode_names.size()) ? s_stretch_mode_names[static_cast<u32>(mode)] : "";
return (static_cast<size_t>(mode) < s_stretch_mode_names.size()) ? s_stretch_mode_names[static_cast<size_t>(mode)] :
"";
}
const char* AudioStream::GetStretchModeDisplayName(AudioStretchMode mode)
{
return (static_cast<u32>(mode) < s_stretch_mode_display_names.size()) ?
Host::TranslateToCString("AudioStream", s_stretch_mode_display_names[static_cast<u32>(mode)]) :
return (static_cast<size_t>(mode) < s_stretch_mode_display_names.size()) ?
Host::TranslateToCString("Settings", s_stretch_mode_display_names[static_cast<size_t>(mode)],
"AudioStretchMode") :
"";
}
std::optional<AudioStretchMode> AudioStream::ParseStretchMode(const char* name)
{
for (u8 i = 0; i < static_cast<u8>(AudioStretchMode::Count); i++)
for (size_t i = 0; i < static_cast<u8>(AudioStretchMode::Count); i++)
{
if (std::strcmp(name, s_stretch_mode_names[i]) == 0)
return static_cast<AudioStretchMode>(i);

View File

@ -14,7 +14,8 @@
Log_SetChannel(Host);
namespace Host {
static std::pair<const char*, u32> LookupTranslationString(std::string_view context, std::string_view msg);
static std::pair<const char*, u32> LookupTranslationString(std::string_view context, std::string_view msg,
std::string_view disambiguation);
static constexpr u32 TRANSLATION_STRING_CACHE_SIZE = 4 * 1024 * 1024;
using TranslationStringMap = PreferUnorderedStringMap<std::pair<u32, u32>>;
@ -25,13 +26,15 @@ static std::vector<char> s_translation_string_cache;
static u32 s_translation_string_cache_pos;
} // namespace Host
std::pair<const char*, u32> Host::LookupTranslationString(std::string_view context, std::string_view msg)
std::pair<const char*, u32> Host::LookupTranslationString(std::string_view context, std::string_view msg,
std::string_view disambiguation)
{
// TODO: TranslatableString, compile-time hashing.
TranslationStringContextMap::iterator ctx_it;
TranslationStringMap::iterator msg_it;
std::pair<const char*, u32> ret;
SmallString disambiguation_key;
s32 len;
// Shouldn't happen, but just in case someone tries to translate an empty string.
@ -42,13 +45,19 @@ std::pair<const char*, u32> Host::LookupTranslationString(std::string_view conte
return ret;
}
if (!disambiguation.empty())
{
disambiguation_key.append(disambiguation);
disambiguation_key.append(msg);
}
s_translation_string_mutex.lock_shared();
ctx_it = s_translation_string_map.find(context);
if (ctx_it == s_translation_string_map.end()) [[unlikely]]
goto add_string;
msg_it = ctx_it->second.find(msg);
msg_it = ctx_it->second.find(disambiguation.empty() ? msg : disambiguation_key.view());
if (msg_it == ctx_it->second.end()) [[unlikely]]
goto add_string;
@ -69,15 +78,15 @@ add_string:
s_translation_string_cache_pos = 0;
}
if ((len =
Internal::GetTranslatedStringImpl(context, msg, &s_translation_string_cache[s_translation_string_cache_pos],
TRANSLATION_STRING_CACHE_SIZE - 1 - s_translation_string_cache_pos)) < 0)
if ((len = Internal::GetTranslatedStringImpl(context, msg, disambiguation,
&s_translation_string_cache[s_translation_string_cache_pos],
TRANSLATION_STRING_CACHE_SIZE - 1 - s_translation_string_cache_pos)) < 0)
{
ERROR_LOG("WARNING: Clearing translation string cache, it might need to be larger.");
s_translation_string_cache_pos = 0;
if ((len =
Internal::GetTranslatedStringImpl(context, msg, &s_translation_string_cache[s_translation_string_cache_pos],
TRANSLATION_STRING_CACHE_SIZE - 1 - s_translation_string_cache_pos)) < 0)
if ((len = Internal::GetTranslatedStringImpl(
context, msg, disambiguation, &s_translation_string_cache[s_translation_string_cache_pos],
TRANSLATION_STRING_CACHE_SIZE - 1 - s_translation_string_cache_pos)) < 0)
{
Panic("Failed to get translated string after clearing cache.");
len = 0;
@ -93,7 +102,8 @@ add_string:
const u32 insert_pos = s_translation_string_cache_pos;
s_translation_string_cache[insert_pos + static_cast<u32>(len)] = 0;
ctx_it->second.emplace(msg, std::pair<u32, u32>(insert_pos, static_cast<u32>(len)));
ctx_it->second.emplace(disambiguation.empty() ? msg : disambiguation_key.view(),
std::pair<u32, u32>(insert_pos, static_cast<u32>(len)));
s_translation_string_cache_pos = insert_pos + static_cast<u32>(len) + 1;
ret.first = &s_translation_string_cache[insert_pos];
@ -102,20 +112,21 @@ add_string:
return ret;
}
const char* Host::TranslateToCString(std::string_view context, std::string_view msg)
const char* Host::TranslateToCString(std::string_view context, std::string_view msg, std::string_view disambiguation)
{
return LookupTranslationString(context, msg).first;
return LookupTranslationString(context, msg, disambiguation).first;
}
std::string_view Host::TranslateToStringView(std::string_view context, std::string_view msg)
std::string_view Host::TranslateToStringView(std::string_view context, std::string_view msg,
std::string_view disambiguation)
{
const auto mp = LookupTranslationString(context, msg);
const auto mp = LookupTranslationString(context, msg, disambiguation);
return std::string_view(mp.first, mp.second);
}
std::string Host::TranslateToString(std::string_view context, std::string_view msg)
std::string Host::TranslateToString(std::string_view context, std::string_view msg, std::string_view disambiguation)
{
return std::string(TranslateToStringView(context, msg));
return std::string(TranslateToStringView(context, msg, disambiguation));
}
void Host::ClearTranslationCache()

View File

@ -50,16 +50,17 @@ bool CopyTextToClipboard(std::string_view text);
/// Returns a localized version of the specified string within the specified context.
/// The pointer is guaranteed to be valid until the next language change.
const char* TranslateToCString(std::string_view context, std::string_view msg);
const char* TranslateToCString(std::string_view context, std::string_view msg, std::string_view disambiguation = {});
/// Returns a localized version of the specified string within the specified context.
/// The view is guaranteed to be valid until the next language change.
/// NOTE: When passing this to fmt, positional arguments should be used in the base string, as
/// not all locales follow the same word ordering.
std::string_view TranslateToStringView(std::string_view context, std::string_view msg);
std::string_view TranslateToStringView(std::string_view context, std::string_view msg,
std::string_view disambiguation = {});
/// Returns a localized version of the specified string within the specified context.
std::string TranslateToString(std::string_view context, std::string_view msg);
std::string TranslateToString(std::string_view context, std::string_view msg, std::string_view disambiguation = {});
/// Returns a localized version of the specified string within the specified context, adjusting for plurals using %n.
std::string TranslatePluralToString(const char* context, const char* msg, const char* disambiguation, int count);
@ -70,7 +71,8 @@ void ClearTranslationCache();
namespace Internal {
/// Implementation to retrieve a translated string.
s32 GetTranslatedStringImpl(std::string_view context, std::string_view msg, char* tbuf, size_t tbuf_space);
s32 GetTranslatedStringImpl(std::string_view context, std::string_view msg, std::string_view disambiguation, char* tbuf,
size_t tbuf_space);
} // namespace Internal
} // namespace Host
@ -79,6 +81,11 @@ s32 GetTranslatedStringImpl(std::string_view context, std::string_view msg, char
#define TRANSLATE_SV(context, msg) Host::TranslateToStringView(context, msg)
#define TRANSLATE_STR(context, msg) Host::TranslateToString(context, msg)
#define TRANSLATE_FS(context, msg) fmt::runtime(Host::TranslateToStringView(context, msg))
#define TRANSLATE_DISAMBIG(context, msg, disambiguation) Host::TranslateToCString(context, msg, disambiguation)
#define TRANSLATE_DISAMBIG_SV(context, msg, disambiguation) Host::TranslateToStringView(context, msg, disambiguation)
#define TRANSLATE_DISAMBIG_STR(context, msg, disambiguation) Host::TranslateToString(context, msg, disambiguation)
#define TRANSLATE_DISAMBIG_FS(context, msg, disambiguation) \
fmt::runtime(Host::TranslateToStringView(context, msg, disambiguation))
#define TRANSLATE_PLURAL_STR(context, msg, disambiguation, count) \
Host::TranslatePluralToString(context, msg, disambiguation, count)
#define TRANSLATE_PLURAL_SSTR(context, msg, disambiguation, count) \
@ -88,3 +95,4 @@ s32 GetTranslatedStringImpl(std::string_view context, std::string_view msg, char
// Does not translate the string at runtime, but allows the UI to in its own way.
#define TRANSLATE_NOOP(context, msg) msg
#define TRANSLATE_DISAMBIG_NOOP(context, msg, disambiguation) msg

View File

@ -2871,10 +2871,10 @@ static constexpr const std::array s_backend_names = {
};
static constexpr const std::array s_backend_display_names = {
#ifdef _WIN32
TRANSLATE_NOOP("MediaCapture", "Media Foundation"),
TRANSLATE_DISAMBIG_NOOP("Settings", "Media Foundation", "MediaCaptureBackend"),
#endif
#ifndef __ANDROID__
TRANSLATE_NOOP("MediaCapture", "FFmpeg"),
TRANSLATE_DISAMBIG_NOOP("Settings", "FFmpeg", "MediaCaptureBackend"),
#endif
};
static_assert(s_backend_names.size() == static_cast<size_t>(MediaCaptureBackend::MaxCount));
@ -2903,7 +2903,8 @@ const char* MediaCapture::GetBackendName(MediaCaptureBackend backend)
const char* MediaCapture::GetBackendDisplayName(MediaCaptureBackend backend)
{
return Host::TranslateToCString("MediaCapture", s_backend_display_names[static_cast<size_t>(backend)]);
return Host::TranslateToCString("Settings", s_backend_display_names[static_cast<size_t>(backend)],
"MediaCaptureBackend");
}
void MediaCapture::AdjustVideoSize(u32* width, u32* height)