localisation.h
The interface's text in the user's language, looked up by the English it was written in.
#include <sonore/localisation.h>- 1type
- 5other declarations
- Guides: Testing your plugin
On this page
Design notes
Why it is here after all
The first answer was that translation belongs upstream: a plugin's parameter names come from its descriptor, and a generated plugin can be generated in any language. That covers parameter names and nothing else. An editor also says "Save preset", "Sample not found", "Click to learn", and every one of those is a string literal in the code. Switching language at runtime, and a translator sending a file rather than a pull request, both need the table at runtime.
The file format
The reference's, so translation files people already have load unchanged:
language: French countries: fr be mc ch lu "Save preset" = "Enregistrer le preset" "Sample \"%s\" not found" = "Échantillon \"%s\" introuvable"
UTF-8, with or without a byte-order mark, or UTF-16 with one (either byte order). One mapping per line, both sides double-quoted. Inside the quotes \" \' \\ \n \t and \r are escapes; any other backslash is kept as written. A line that is not a mapping, a language or a countries line is ignored -- which is how comments work, whatever they start with. A mapping that cannot be read (a missing quote, no '=') is skipped and its line number recorded, so a translator can be told where the file is wrong rather than wondering why one string stayed English. (The one difference from the reference: it does not treat \\ as an escape, so a string ending in a backslash could not be written at all.)
Threads
The current mapping is an IMMUTABLE snapshot held by a shared_ptr. translate() takes a short lock only to copy that pointer, then looks up without it; setCurrentMappings() swaps the pointer under the same lock. A lookup that started against the old table finishes against it, and the old table is freed by whichever side lets go last. So the editor can translate from any thread while the user changes language -- but not from the audio thread: a lookup returns a std::string, which allocates.
Types 1
A table of translations, keyed by the original (English) text, with an optional fallback table consulted for anything this one lacks.
Functions 3
- fn
inline std::string translate(const std::string& text)localisation.h:467texttranslated by the current mappings, ortextitself if there are none or they lack it. What SONORE_TRANS expands to. - fn
inline std::string translate(const char* text)The same for a C string; a null pointer is "".localisation.h:471 - fn
inline std::string translate(const std::string& text, const std::string& resultIfNotFound)localisation.h:475texttranslated, orresultIfNotFoundwhen no current table has it.
Macros 2
- macro
#define SONORE_TRANS(stringLiteral) ::sonore::translate(stringLiteral)Marks a literal as interface text and translates it. A script that scans sources for SONORE_TRANS("...") finds every string a translator needs.localisation.h:484 - macro
#define SONORE_NEEDS_TRANS(stringLiteral) (stringLiteral)Marks a literal for translation WITHOUT translating it here -- for text stored now and translated when shown (a table of menu entries, say).localisation.h:488