const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) { #define STATIC_LOCALE_SIZE 32 /* Should be more than enough! */ GHashKey *key; static char locale[STATIC_LOCALE_SIZE] = ""; const char *tmp; /* Just in case, should never happen! */ if (!_translations) return msgid; tmp = BLF_lang_get(); if (strcmp(tmp, locale) || !_translations_cache) { PyGILState_STATE _py_state; BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE); /* Locale changed or cache does not exist, refresh the whole cache! */ /* This func may be called from C (i.e. outside of python interpreter 'context'). */ _py_state = PyGILState_Ensure(); _build_translations_cache(_translations->py_messages, locale); PyGILState_Release(_py_state); } /* And now, simply create the key (context, messageid) and find it in the cached dict! */ key = _ghashutil_keyalloc(msgctxt, msgid); tmp = BLI_ghash_lookup(_translations_cache, key); _ghashutil_keyfree((void *)key); return tmp ? tmp : msgid; #undef STATIC_LOCALE_SIZE }
static void _build_translations_cache(PyObject *py_messages, const char *locale) { PyObject *uuid, *uuid_dict; Py_ssize_t pos = 0; char *language = NULL, *language_country = NULL, *language_variant = NULL; /* For each py dict, we'll search for full locale, then language+country, then language+variant, * then only language keys... */ BLT_lang_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant); /* Clear the cached ghash if needed, and create a new one. */ _clear_translations_cache(); _translations_cache = BLI_ghash_new(_ghashutil_keyhash, _ghashutil_keycmp, __func__); /* Iterate over all py dicts. */ while (PyDict_Next(py_messages, &pos, &uuid, &uuid_dict)) { PyObject *lang_dict; #if 0 PyObject_Print(uuid_dict, stdout, 0); printf("\n"); #endif /* Try to get first complete locale, then language+country, then language+variant, then only language */ lang_dict = PyDict_GetItemString(uuid_dict, locale); if (!lang_dict && language_country) { lang_dict = PyDict_GetItemString(uuid_dict, language_country); locale = language_country; } if (!lang_dict && language_variant) { lang_dict = PyDict_GetItemString(uuid_dict, language_variant); locale = language_variant; } if (!lang_dict && language) { lang_dict = PyDict_GetItemString(uuid_dict, language); locale = language; } if (lang_dict) { PyObject *pykey, *trans; Py_ssize_t ppos = 0; if (!PyDict_Check(lang_dict)) { printf("WARNING! In translations' dict of \""); PyObject_Print(uuid, stdout, Py_PRINT_RAW); printf("\":\n"); printf(" Each language key must have a dictionary as value, \"%s\" is not valid, skipping: ", locale); PyObject_Print(lang_dict, stdout, Py_PRINT_RAW); printf("\n"); continue; } /* Iterate over all translations of the found language dict, and populate our ghash cache. */ while (PyDict_Next(lang_dict, &ppos, &pykey, &trans)) { const char *msgctxt = NULL, *msgid = NULL; bool invalid_key = false; if ((PyTuple_CheckExact(pykey) == false) || (PyTuple_GET_SIZE(pykey) != 2)) { invalid_key = true; } else { PyObject *tmp = PyTuple_GET_ITEM(pykey, 0); if (tmp == Py_None) { msgctxt = BLT_I18NCONTEXT_DEFAULT_BPYRNA; } else if (PyUnicode_Check(tmp)) { msgctxt = _PyUnicode_AsString(tmp); } else { invalid_key = true; } tmp = PyTuple_GET_ITEM(pykey, 1); if (PyUnicode_Check(tmp)) { msgid = _PyUnicode_AsString(tmp); } else { invalid_key = true; } } if (invalid_key) { printf("WARNING! In translations' dict of \""); PyObject_Print(uuid, stdout, Py_PRINT_RAW); printf("\", %s language:\n", locale); printf(" Keys must be tuples of (msgctxt [string or None], msgid [string]), " "this one is not valid, skipping: "); PyObject_Print(pykey, stdout, Py_PRINT_RAW); printf("\n"); continue; } if (PyUnicode_Check(trans) == false) { printf("WARNING! In translations' dict of \""); PyObject_Print(uuid, stdout, Py_PRINT_RAW); printf("\":\n"); printf(" Values must be strings, this one is not valid, skipping: "); PyObject_Print(trans, stdout, Py_PRINT_RAW); printf("\n"); continue; } /* Do not overwrite existing keys! */ if (BPY_app_translations_py_pgettext(msgctxt, msgid) == msgid) { GHashKey *key = _ghashutil_keyalloc(msgctxt, msgid); BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans))); } } } } /* Clean up! */ MEM_SAFE_FREE(language); MEM_SAFE_FREE(language_country); MEM_SAFE_FREE(language_variant); }