10#include "SDL_locale.h"
25typedef struct translation {
45 char *
const *available );
55 const char *env_vars[] = {
"LANGUAGE",
"LC_ALL",
"LC_MESSAGES",
"LANG" };
57 setlocale( LC_ALL,
"" );
60 setlocale( LC_NUMERIC,
"C" );
63 SDL_Locale *locales = SDL_GetPreferredLocales();
64 if ( locales != NULL ) {
65 if ( locales[0].language != NULL ) {
74 for (
size_t i = 0; i <
sizeof( env_vars ) /
sizeof( env_vars[0] ); i++ ) {
75 const char *language = SDL_getenv( env_vars[i] );
76 if ( language != NULL && *language != 0 ) {
138 char root[256], **paths, **available_langs;
148 ptrans = ptrans->next )
149 if ( !strcmp( lang, ptrans->language ) ) {
156 newtrans->
language = strdup( lang );
162 available_langs = PHYSFS_enumerateFiles( GETTEXT_PATH );
167 while ( lang != NULL && *lang != 0 ) {
168 size_t map_size, lang_part_len;
169 const char *lang_part = lang, *lang_match;
170 lang = strchr( lang,
':' );
172 lang_part_len = strlen( lang_part );
174 lang_part_len = (size_t)( lang - lang_part );
179 if ( lang_match == NULL )
181 snprintf( root,
sizeof( root ), GETTEXT_PATH
"%s", lang_match );
183 for (
int i = 0; i <
array_size( paths ); i++ ) {
184 const char *map =
ndata_read( paths[i], &map_size );
188 DEBUG( _(
"Adding translations from %s" ), paths[i] );
194 PHYSFS_freeList( available_langs );
205 char *
const *available )
207 const char *best = NULL;
214 for (
size_t i = 0; available[i] != NULL; i++ ) {
216 strncmp( lang, available[i],
MIN( lang_len, strlen( available[i] ) ) );
243 for (
int i = 0; i <
array_size( chain ); i++ ) {
247 return (
char *)trans;
251 return ( ( ( n > 1 ) || ( n == 0 ) ) && msgid_plural != NULL ) ? msgid_plural
261 const char *trans = _( lookup );
262 return trans == lookup ? msgid : trans;
274 for (
int i = 0; i <
array_size( paths ); i++ ) {
292 LanguageOption en = { .language = strdup(
"en" ), .coverage = 1. };
293 char **dirs = PHYSFS_enumerateFiles( GETTEXT_PATH );
296 for (
size_t i = 0; dirs[i] != NULL; i++ ) {
301 PHYSFS_freeList( dirs );
314 uint32_t translated = 0;
315 char **paths, dirpath[
PATH_MAX], buf[12];
318 if ( !strcmp( lang,
"en" ) )
325 snprintf( dirpath,
sizeof( dirpath ), GETTEXT_PATH
"%s", lang );
327 for (
int j = 0; j <
array_size( paths ); j++ ) {
330 file = PHYSFS_openRead( paths[j] );
334 size = PHYSFS_readBytes( file, buf, 12 );
350 SDL_asprintf( &lookup,
"%s" GETTEXT_CONTEXT_GLUE
"%s", msgctxt, msgid );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
const char * gettext_ngettext(const char *msgid, const char *msgid_plural, uint64_t n)
Return a translated version of the input, using the current language catalogs.
void gettext_exit(void)
Free resources associated with the translation system. This invalidates previously returned pointers ...
static translation_t * gettext_activeTranslation
double gettext_languageCoverage(const char *lang)
Return the fraction of strings which have a translation into the given language.
void gettext_setLanguage(const char *lang)
Set the translation language.
const char * gettext_getLanguage(void)
Gets the active (primary) translation language. Even in case of a complex locale, this will be the na...
const char * pgettext_var(const char *msgctxt, const char *msgid)
static void gettext_readStats(void)
Read the GETTEXT_STATS_PATH data and compute gettext_nstrings. (Common case: just a "naev....
static translation_t * gettext_translations
static char * gettext_systemLanguage
LanguageOption * gettext_languageOptions(void)
List the available languages, with completeness statistics.
const char * gettext_getSystemLanguage(void)
Gets the current system language as detected by Naev.
static uint32_t gettext_nstrings
void gettext_init(void)
Initialize the translation system. There's no presumption that PhysicsFS is available,...
static const char * gettext_matchLanguage(const char *lang, size_t lang_len, char *const *available)
Pick the best match from "available" (a physfs listing) for the string-slice with address lang,...
const char * gettext_pgettext_impl(const char *lookup, const char *msgid)
Helper function for p_(): Return _(lookup) with a fallback of msgid rather than lookup.
const char * msgcat_ngettext(const msgcat_t *p, const char *msgid1, const char *msgid2, uint64_t n)
Return a translation, if present, from the given message catalog.
void msgcat_init(msgcat_t *p, const void *map, size_t map_size)
Initialize a msgcat_t, given the contents and content-length of a .mo file.
uint32_t msgcat_nstringsFromHeader(const char buf[12])
Return the number of strings in a message catalog, given its first 12 bytes.
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
struct translation * next