Browse Source

Merge branch 'release/1.9.x'

rdb 10 years ago
parent
commit
d13b43f003

+ 6 - 0
direct/src/p3d/DeploymentTools.py

@@ -99,6 +99,9 @@ class Standalone:
         if len(platforms) == 0:
             Standalone.notify.warning("No platforms found to build for!")
 
+        if 'win32' in platforms and 'win_i386' in platforms:
+            platforms.remove('win32')
+
         outputDir = Filename(outputDir + "/")
         outputDir.makeDir()
         for platform in platforms:
@@ -669,6 +672,9 @@ class Installer:
         if len(platforms) == 0:
             Installer.notify.warning("No platforms found to build for!")
 
+        if 'win32' in platforms and 'win_i386' in platforms:
+            platforms.remove('win32')
+
         outputDir = Filename(outputDir + "/")
         outputDir.makeDir()
         for platform in platforms:

+ 3 - 2
direct/src/plugin/p3dAuthSession.cxx

@@ -183,7 +183,7 @@ start_p3dcert() {
   // These are the enviroment variables we forward from the current
   // environment, if they are set.
   const wchar_t *keep[] = {
-    L"TMP", L"TEMP", L"HOME", L"USER", 
+    L"TMP", L"TEMP", L"HOME", L"USER",
     L"SYSTEMROOT", L"USERPROFILE", L"COMSPEC",
     NULL
   };
@@ -209,7 +209,8 @@ start_p3dcert() {
   // These are the enviroment variables we forward from the current
   // environment, if they are set.
   const char *keep[] = {
-    "TMP", "TEMP", "HOME", "USER", 
+    "TMP", "TEMP", "HOME", "USER",
+    "LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG",
 #ifdef HAVE_X11
     "DISPLAY", "XAUTHORITY",
 #endif

+ 162 - 59
direct/src/plugin/p3dCert.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "p3dCert.h"
+#include "p3dCert_strings.h"
 #include "wstring_encode.h"
 #include "mkdir_complete.h"
 
@@ -26,8 +27,9 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <limits.h>
+#include <locale.h>
 
-#define BUTTON_WIDTH 120
+#define BUTTON_WIDTH 180 // fit the Russian text
 #define BUTTON_SPACE 10
 
 #include "ca_bundle_data_src.c"
@@ -36,63 +38,152 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <shellapi.h>
+#include <malloc.h>
 
 #define snprintf sprintf_s
 #endif
 
-static const char
-self_signed_cert_text[] =
-  "This Panda3D application uses a self-signed certificate.  "
-  "This means the author's name can't be verified, and you have "
-  "no way of knowing for sure who wrote it.\n\n"
+#ifdef __APPLE__
+#include <CoreFoundation/CoreFoundation.h>
+#endif
 
-  "We recommend you click Cancel to avoid running this application.";
+static LanguageIndex li = LI_default;
+
+#if defined(_WIN32)
+static LanguageIndex detect_language() {
+  // This function was introduced in Windows Vista; it may not be available
+  // on older systems.
+  typedef BOOL (*GUPL)(DWORD, PULONG, PZZWSTR, PULONG);
+  GUPL pGetUserPreferredUILanguages = (GUPL)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
+                                                           TEXT("GetUserPreferredUILanguages"));
+  if (pGetUserPreferredUILanguages != NULL) {
+    ULONG num_langs = 0;
+    ULONG buffer_size = 0;
+    pGetUserPreferredUILanguages(8, &num_langs, NULL, &buffer_size);
+    PZZWSTR buffer = (PZZWSTR)_alloca(buffer_size);
+    if (pGetUserPreferredUILanguages(8, &num_langs, buffer, &buffer_size)) {
+      for (ULONG i = 0; i < num_langs; ++i) {
+        size_t len = wcslen(buffer);
+        if (len >= 2 && (buffer[2] == 0 || buffer[2] == L'-')) {
+          // It may be a two-letter code; match it in our list.
+          for (int j = 0; j < LI_COUNT; ++j) {
+            const char *lang_code = language_codes[j];
+            if (lang_code != NULL && lang_code[0] == buffer[0] &&
+                                     lang_code[1] == buffer[1]) {
+              return (LanguageIndex)j;
+            }
+          }
+        }
+        buffer += len + 1;
+      }
+    }
+  }
 
-static const char
-unknown_auth_cert_text[] =
-  "This Panda3D application has been signed, but we don't recognize "
-  "the authority that verifies the signature.  This means the author's "
-  "name can't be trusted, and you have no way of knowing "
-  "for sure who wrote it.\n\n"
+  // Fall back to the old Windows XP function.
+  LANGID lang = GetUserDefaultUILanguage() & 0x3ff;
+  if (lang == 0) {
+    return LI_default;
+  }
 
-  "We recommend you click Cancel to avoid running this application.";
+  for (int i = 0; i < LI_COUNT; ++i) {
+    if (language_ids[i] != 0 && language_ids[i] == lang) {
+      return (LanguageIndex)i;
+    }
+  }
+  return LI_default;
+}
 
-static const char
-verified_cert_text[] =
-  "This Panda3D application has been signed by %s. "
-  "If you trust %s, then click the Run button below "
-  "to run this application on your computer.  This will also "
-  "automatically approve this and any other applications signed by "
-  "%s in the future.\n\n"
+#elif defined(__APPLE__)
+static LanguageIndex detect_language() {
+  // Get and iterate through the list of preferred languages.
+  CFArrayRef langs = CFLocaleCopyPreferredLanguages();
+  CFIndex num_langs = CFArrayGetCount(langs);
 
-  "If you are unsure about this application, "
-  "you should click Cancel instead.";
+  for (long i = 0; i < num_langs; ++i) {
+    CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
 
-static const char
-expired_cert_text[] =
-  "This Panda3D application has been signed by %s, "
-  "but the certificate has expired.\n\n"
+    CFIndex length = CFStringGetLength(lang);
+    if (length < 2) {
+      continue;
+    }
 
-  "You should check the current date set on your computer's clock "
-  "to make sure it is correct.\n\n"
+    CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+    char *buffer = (char *)alloca(max_size);
+    if (!CFStringGetCString(lang, buffer, max_size, kCFStringEncodingUTF8)) {
+      continue;
+    }
 
-  "If your computer's date is correct, we recommend "
-  "you click Cancel to avoid running this application.";
+    if (isalnum(buffer[2])) {
+      // It's not a two-letter code.
+      continue;
+    }
 
-static const char
-generic_error_cert_text[] =
-  "This Panda3D application has been signed, but there is a problem "
-  "with the certificate (OpenSSL error code %d).\n\n"
+    // See if we support this language.
+    for (int j = 0; j < LI_COUNT; ++j) {
+      const char *lang_code = language_codes[j];
+      if (lang_code != NULL && strncasecmp(buffer, lang_code, 2) == 0) {
+        CFRelease(langs);
+        return (LanguageIndex)j;
+      }
+    }
+  }
 
-  "We recommend you click Cancel to avoid running this application.";
+  CFRelease(langs);
+  return LI_default;
+}
 
-static const char
-no_cert_text[] =
-  "This Panda3D application has not been signed.  This means you have "
-  "no way of knowing for sure who wrote it.\n\n"
+#else
+static LanguageIndex detect_language() {
+  // First consult the LANGUAGE variable, which is a GNU extension that can
+  // contain multiple languages in order of preference.
+  const char *lang = getenv("LANGUAGE");
+  while (lang != NULL && lang[0] != 0) {
+    size_t len;
+    const char *next = strchr(lang, ':');
+    if (next == NULL) {
+      len = strlen(lang);
+    } else {
+      len = (next - lang);
+      ++next;
+    }
 
-  "Click Cancel to avoid running this application.";
+    if (len >= 2 && !isalnum(lang[2])) {
+      // It may be a two-letter language code; match it in our list.
+      for (int i = 0; i < LI_COUNT; ++i) {
+        const char *lang_code = language_codes[i];
+        if (lang_code != NULL && strncasecmp(lang, lang_code, 2) == 0) {
+          return (LanguageIndex)i;
+        }
+      }
+    }
+
+    lang = next;
+  }
+
+  // Fall back to the C locale functions.
+  setlocale(LC_ALL, "");
+  lang = setlocale(LC_MESSAGES, NULL);
+
+  if (lang == NULL || lang[0] == 0 || strcmp(lang, "C") == 0) {
+    // Try the LANG variable.
+    lang = getenv("LANG");
+  }
+
+  if (lang == NULL || strlen(lang) < 2 || isalnum(lang[2])) {
+    // Couldn't extract a meaningful two-letter code.
+    return LI_default;
+  }
 
+  // It may be a two-letter language code; match it in our list.
+  for (int i = 0; i < LI_COUNT; ++i) {
+    const char *lang_code = language_codes[i];
+    if (lang_code != NULL && strncasecmp(lang, lang_code, 2) == 0) {
+      return (LanguageIndex)i;
+    }
+  }
+  return LI_default;
+}
+#endif
 
 #ifdef _WIN32
 int WINAPI
@@ -107,6 +198,8 @@ wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdS
     return 1;
   }
 
+  li = detect_language();
+
   wstring cert_filename (argv[0]);
   wstring cert_dir (argv[1]);
   LocalFree(argv);
@@ -126,6 +219,8 @@ int main(int argc, char **argv) {
     return 1;
   }
 
+  li = detect_language();
+
   string cert_filename (argv[1]);
   string cert_dir (argv[2]);
 
@@ -148,7 +243,7 @@ AuthDialog(const wstring &cert_filename, const wstring &cert_dir) :
 AuthDialog::
 AuthDialog(const string &cert_filename, const string &cert_dir) :
 #endif
-  Fl_Window(435, 242, "New Panda3D Application"),
+  Fl_Window(435, 242, new_application_title[li]),
   _cert_dir(cert_dir)
 {
   _view_cert_dialog = NULL;
@@ -315,12 +410,20 @@ read_cert_file(const string &cert_filename) {
 #endif  // _WIN32
 
   if (fp == NULL) {
+#ifdef _WIN32
+    wcerr << L"Couldn't read " << cert_filename.c_str() << L"\n";
+#else
     cerr << "Couldn't read " << cert_filename.c_str() << "\n";
+#endif
     return;
   }
   _cert = PEM_read_X509(fp, NULL, NULL, (void *)"");
   if (_cert == NULL) {
+#ifdef _WIN32
+    wcerr << L"Could not read certificate in " << cert_filename.c_str() << L".\n";
+#else
     cerr << "Could not read certificate in " << cert_filename.c_str() << ".\n";
+#endif
     fclose(fp);
     return;
   }
@@ -510,19 +613,19 @@ layout() {
   short bx = (w() - nbuttons * BUTTON_WIDTH - (nbuttons - 1) * BUTTON_SPACE) / 2;
 
   if (_verify_result == 0 && _cert != NULL) {
-    Fl_Return_Button *run_button = new Fl_Return_Button(bx, next_y, BUTTON_WIDTH, 25, "Run");
+    Fl_Return_Button *run_button = new Fl_Return_Button(bx, next_y, BUTTON_WIDTH, 25, run_title[li]);
     run_button->callback(this->run_clicked, this);
     bx += BUTTON_WIDTH + BUTTON_SPACE;
   }
 
   if (_cert != NULL) {
-    Fl_Button *view_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, "View Certificate");
+    Fl_Button *view_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, show_cert_title[li]);
     view_button->callback(this->view_cert_clicked, this);
     bx += BUTTON_WIDTH + BUTTON_SPACE;
   }
 
   Fl_Button *cancel_button;
-  cancel_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, "Cancel");
+  cancel_button = new Fl_Button(bx, next_y, BUTTON_WIDTH, 25, cancel_title[li]);
   cancel_button->callback(this->cancel_clicked, this);
 
   next_y += 42;
@@ -542,12 +645,12 @@ void AuthDialog::
 get_text(char *header, size_t hlen, char *text, size_t tlen) {
   switch (_verify_result) {
   case -1:
-    strncpy(header, "No signature!", hlen);
-    strncpy(text, no_cert_text, tlen);
+    strncpy(header, no_cert_title[li], hlen);
+    strncpy(text, no_cert_text[li], tlen);
     break;
 
   case 0:
-    snprintf(text, tlen, verified_cert_text, _friendly_name.c_str(),
+    snprintf(text, tlen, verified_cert_text[li], _friendly_name.c_str(),
                         _friendly_name.c_str(), _friendly_name.c_str());
     break;
 
@@ -555,24 +658,24 @@ get_text(char *header, size_t hlen, char *text, size_t tlen) {
   case X509_V_ERR_CERT_HAS_EXPIRED:
   case X509_V_ERR_CRL_NOT_YET_VALID:
   case X509_V_ERR_CRL_HAS_EXPIRED:
-    strncpy(header, "Expired signature!", hlen);
-    snprintf(text, tlen, expired_cert_text, _friendly_name.c_str());
+    strncpy(header, expired_cert_title[li], hlen);
+    snprintf(text, tlen, expired_cert_text[li], _friendly_name.c_str());
     break;
 
   case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
-    strncpy(header, "Unverified signature!", hlen);
-    snprintf(text, tlen, unknown_auth_cert_text);
+    strncpy(header, unverified_cert_title[li], hlen);
+    strncpy(text, unknown_auth_cert_text[li], tlen);
     break;
 
   case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
   case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
-    strncpy(header, "Unverified signature!", hlen);
-    strncpy(text, self_signed_cert_text, tlen);
+    strncpy(header, unverified_cert_title[li], hlen);
+    strncpy(text, self_signed_cert_text[li], tlen);
     break;
 
   default:
-    strncpy(header, "Unverified signature!", hlen);
-    snprintf(text, tlen, generic_error_cert_text, _verify_result);
+    strncpy(header, unverified_cert_title[li], hlen);
+    snprintf(text, tlen, generic_error_cert_text[li], _verify_result);
   }
 }
 
@@ -583,7 +686,7 @@ get_text(char *header, size_t hlen, char *text, size_t tlen) {
 ////////////////////////////////////////////////////////////////////
 ViewCertDialog::
 ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
-  Fl_Window(600, 400, "View Certificate"),
+  Fl_Window(600, 400, show_cert_title[li]),
   _auth_dialog(auth_dialog),
   _cert(cert)
 {
@@ -660,12 +763,12 @@ layout() {
 
   short bx = (w() - BUTTON_WIDTH * 2 - BUTTON_SPACE) / 2;
 
-  Fl_Return_Button *run_button = new Fl_Return_Button(bx, 360, BUTTON_WIDTH, 25, "Run");
+  Fl_Return_Button *run_button = new Fl_Return_Button(bx, 360, BUTTON_WIDTH, 25, run_title[li]);
   run_button->callback(this->run_clicked, this);
 
   bx += BUTTON_WIDTH + BUTTON_SPACE;
 
-  Fl_Button *cancel_button = new Fl_Button(bx, 360, BUTTON_WIDTH, 25, "Cancel");
+  Fl_Button *cancel_button = new Fl_Button(bx, 360, BUTTON_WIDTH, 25, cancel_title[li]);
   cancel_button->callback(this->cancel_clicked, this);
 
   end();

+ 3 - 3
direct/src/plugin/p3dCert.h

@@ -92,9 +92,9 @@ private:
   X509 *_cert;
   STACK_OF(X509) *_stack;
 
-  char _header[32];
-  char _text[512];
-  char _text_clean[1024];
+  char _header[64];
+  char _text[1024];
+  char _text_clean[2048];
 
   string _friendly_name;
   int _verify_result;

+ 571 - 0
direct/src/plugin/p3dCert_strings.cxx

@@ -0,0 +1,571 @@
+// Filename: p3dCert_strings.h
+// Created by:  rdb (25Mar15)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "p3dCert_strings.h"
+
+// Translations kindly provided by:
+// eng: drwr
+// nld: rdb
+// deu: Sebastian Hoffmann <TheCheapestPixels at googlemail dot com>
+// spa: Imanol Celaya <imanol at celaya dot me>
+// ita: Flavio Clava
+// rus: montreal
+
+const char *language_codes[LI_COUNT] =
+  {"en", "nl", "de", "es", "it", "eo", "ru"};
+
+// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693%28v=vs.85%29.aspx
+const unsigned char language_ids[LI_COUNT] =
+  {0x09, 0x13, 0x07, 0x0A, 0x10, 0x8F, 0x19};
+
+const char *
+run_title[LI_COUNT] = {
+  "Run",
+  "Uitvoeren",
+  "Starten",
+  "Ejecutar",
+  "Lancia",
+  "Lan\304\211i",
+  "\320\227\320\260\320\277\321\203\321\201\321\202\320\270\321\202\321\214",
+};
+
+const char *
+cancel_title[LI_COUNT] = {
+  "Cancel",
+  "Annuleren",
+  "Abbrechen",
+  "Cancelar",
+  "Cancella",
+  "Nuligi",
+  "\320\236\321\202\320\274\320\265\320\275\320\260",
+};
+
+const char *
+show_cert_title[LI_COUNT] = {
+  "Show Certificate",
+  "Toon Certificaat",
+  "Zertifikat anzeigen",
+  "Mostrar certificado",
+  "Mostra certificato",
+  "Montri Ateston",
+  "\320\237\320\276\320\272\320\260\320\267\320\260\321\202\321\214 \321\201"
+  "\320\265\321\200\321\202\320\270\321\204\320\270\320\272\320\260\321\202",
+};
+
+const char *
+new_application_title[LI_COUNT] = {
+  "New Panda3D Application",
+  "Nieuwe Panda3D Applicatie",
+  "Neue Panda3D-Anwendung",
+  "Nueva aplicaci\303\263n de Panda3D",
+  "Nuova applicazione Panda3D",
+  "Nova aplika\304\265o de Panda3D",
+  "\320\235\320\276\320\262\320\276\320\265 Panda3D-\320\277\321\200\320\270"
+  "\320\273\320\276\320\266\320\265\320\275\320\270\320\265",
+};
+
+const char *
+no_cert_title[LI_COUNT] = {
+  "No signature!",
+  "Geen handtekening!",
+  "Keine Signatur!",
+  "Sin firma!",
+  "Nessuna firma!",
+  "Ne subskribo!",
+  "\320\235\320\265\321\202 \320\277\320\276\320\264\320\277\320\270\321\201"
+  "\320\270!",
+};
+
+const char *
+unverified_cert_title[LI_COUNT] = {
+  "Unverified signature!",
+  "Ongeverifieerde handtekening!",
+  "Unbest\303\244tigte Signatur!",
+  "Firma sin verificar!",
+  "Firma non verificata!",
+  "Nekontrolita subskribo!",
+  "\320\235\320\265\320\277\321\200\320\276\320\262\320\265\321\200\320\265"
+  "\320\275\320\275\320\260\321\217 \320\277\320\276\320\264\320\277\320\270"
+  "\321\201\321\214!",
+};
+
+const char *
+expired_cert_title[LI_COUNT] = {
+  "Expired signature!",
+  "Verlopen handtekening!",
+  "Abgelaufene Signatur!",
+  "Firma caducada!",
+  "Firma scaduta!",
+  "Eksvalidi\304\235inta subskribo!",
+  "\320\241\321\200\320\276\320\272 \320\264\320\265\320\271\321\201\321\202"
+  "\320\262\320\270\321\217 \320\277\320\276\320\264\320\277\320\270\321\201"
+  "\320\270 \320\270\321\201\321\202\321\221\320\272!",
+};
+
+
+const char *
+self_signed_cert_text[LI_COUNT] = {
+  // eng
+  "This Panda3D application uses a self-signed certificate.  "
+  "This means the author's name can't be verified, and you have "
+  "no way of knowing for sure who wrote it.\n"
+  "\n"
+  "We recommend you click Cancel to avoid running this application.",
+
+  // nld
+  "Deze Panda3D applicatie gebruikt een zelf-getekend certificaat.  "
+  "Dit betekent dat de auteursnaam niet kan worden geverifieerd, en het "
+  "niet zeker is of de applicatie te vertrouwen is.\n"
+  "\n"
+  "Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
+  "sluiten.",
+
+  // deu
+  "Diese Panda3D-Anwendung benutzt ein selbst-signiertes Zertifikat.  Dies "
+  "bedeutet, dass weder der Name des Autors \303\274berpr\303\274ft werden "
+  "kann, noch dass garantiert werden kann, dass tats\303\244chlich die "
+  "angegebene Person diese Anwendung geschrieben hat.\n"
+  "\n"
+  "Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
+  "auszuf\303\274hren.",
+
+  // spa
+  "Esta aplicaci\303\263n de Panda3D usa un certificado autofirmado.  "
+  "Esto significa que el nombre del autor no puede ser verificado y no se "
+  "puede conocer seguro quien la ha escrito.\n"
+  "\n"
+  "Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
+
+  // ita
+  "Questa applicazione Panda3D usa un certificato autofirmato.  Ci\303\262 "
+  "significa che il nome dell'autore non pu\303\262 essere verificato, e "
+  "che non hai modo di assicurarti circa chi la abbia scritta.\n"
+  "\n"
+  "Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
+  "applicazione.",
+
+  // epo
+  "\304\210i tiu aplika\304\265o de Panda3D uzas memsubskribitan ateston.  "
+  "Tio signifas  ke la nomo de la verkanto ne povas esti kontrolita, kaj vi "
+  "ne havas certan scimanieron pri la vera verkanto de la aplika\304\265o.\n"
+  "\n"
+  "Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on de "
+  "\304\211i tiu aplika\304\265o.",
+
+  // rus
+  "\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
+  "\320\265\320\275\320\270\320\265 \320\270\321\201\320\277\320\276\320\273"
+  "\321\214\320\267\321\203\320\265\321\202 \321\201\320\260\320\274\320\276"
+  "\320\267\320\260\320\262\320\265\321\200\320\265\320\275\320\275\321\213"
+  "\320\271 \321\201\320\265\321\200\321\202\320\270\321\204\320\270\320\272"
+  "\320\260\321\202.  \320\255\321\202\320\276 \320\276\320\267\320\275"
+  "\320\260\321\207\320\260\320\265\321\202, \321\207\321\202\320\276 "
+  "\320\270\320\274\321\217 \320\260\320\262\321\202\320\276\321\200\320\260 "
+  "\320\275\320\265 \320\274\320\276\320\266\320\265\321\202 \320\261\321\213"
+  "\321\202\321\214 \320\277\320\276\320\264\321\202\320\262\320\265\320\266"
+  "\320\264\320\265\320\275\320\276, \320\270 \320\262\321\213 \320\275"
+  "\320\265 \320\274\320\276\320\266\320\265\321\202\320\265 \320\267\320\275"
+  "\320\260\321\202\321\214, \320\272\321\202\320\276 \320\275\320\260"
+  "\320\277\320\270\321\201\320\260\320\273 \321\215\321\202\320\276 \320\277"
+  "\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.\n"
+  "\n"
+  "\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
+  "\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
+  "\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
+  "\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
+  "\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
+  "\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
+  "\320\265.",
+};
+
+
+const char *
+unknown_auth_cert_text[LI_COUNT] = {
+  "This Panda3D application has been signed, but we don't recognize "
+  "the authority that verifies the signature.  This means the author's "
+  "name can't be verified, and you have no way of knowing "
+  "for sure who wrote it.\n"
+  "\n"
+  "We recommend you click Cancel to avoid running this application.",
+
+   // nld
+  "Deze Panda3D applicatie is ondertekend, maar de certificaatautoriteit "
+  "die het certificaat heeft uitgegeven wordt niet herkend.  Dit betekent "
+  "dat de auteursnaam niet te vertrouwen is, en het niet zeker is wie de "
+  "applicatie gemaakt heeft.\n"
+  "\n"
+  "Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
+  "sluiten.",
+
+  // deu
+  "Diese Panda3D-Anwendung wurde signiert, aber die "
+  "\303\234berpr\303\274fungsstelle wurde nicht anerkannt.  Dies bedeutet, "
+  "dass weder der Name des Autors \303\274berpr\303\274ft werden kann, noch "
+  "dass garantiert werden kann, dass tats\303\244chlich die angegebene "
+  "Person diese Anwendung geschrieben hat.\n"
+  "\n"
+  "Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
+  "auszuf\303\274hren.",
+
+  // spa
+  "Esta aplicaci\303\263n de Panda3D esta firmada, pero no reconocemos la "
+  "autoridad que la verifica.  Esto significa que el nombre del autor no "
+  "puede ser verificado y no se puede conocer seguro quien la ha escrito.\n"
+  "\n"
+  "Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
+
+  // ita
+  "Questa applicazione Panda3D \303\250 stata firmata, ma non riconosciamo "
+  "l'autorit\303\240 che verifica la firma. Ci\303\262 significa che il "
+  "nome dell'autore non pu\303\262 essere verificato, e che non hai modo "
+  "di assicurarti circa chi la abbia scritta.\n"
+  "\n"
+  "Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
+  "applicazione.",
+
+  // epo
+  "\304\210i tiu aplika\304\265o estas subskribita, sed ni ne rekonas "
+  "la a\305\255toritaton, kiu kontrolas la subskribon. Tio signifas ke la "
+  "nomo de la verkanto ne povas esti konfidata, kaj vi ne havas certan "
+  "scimanieron pri la vera verkanto de la aplika\304\265o.\n"
+  "\n"
+  "Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on "
+  "de \304\211i tiu aplika\304\265o.",
+
+  // rus
+  "\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
+  "\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\265\321\201"
+  "\321\202\321\214 \320\277\320\276\320\264\320\277\320\270\321\201\321\214,"
+  " \320\277\320\276 \320\272\320\276\321\202\320\276\321\200\320\276\320\271"
+  " \320\274\321\213 \320\275\320\265 \320\274\320\276\320\266\320\265"
+  "\320\274 \321\200\320\260\321\201\320\277\320\276\320\267\320\275\320\260"
+  "\321\202\321\214 \320\262\320\273\320\260\320\264\320\265\320\273\321\214"
+  "\321\206\320\260.  \320\255\321\202\320\276 \320\276\320\267\320\275"
+  "\320\260\321\207\320\260\320\265\321\202, \321\207\321\202\320\276 "
+  "\320\270\320\274\321\217 \320\260\320\262\321\202\320\276\321\200\320\260 "
+  "\320\275\320\265 \320\274\320\276\320\266\320\265\321\202 \320\261\321\213"
+  "\321\202\321\214 \320\276\320\277\321\200\320\265\320\264\320\265\320\273"
+  "\320\265\320\275\320\276, \320\270 \320\275\320\265\320\262\320\276"
+  "\320\267\320\274\320\276\320\266\320\275\320\276 \321\202\320\276\321\207"
+  "\320\275\320\276 \321\203\320\267\320\275\320\260\321\202\321\214, "
+  "\320\272\321\202\320\276 \320\275\320\260\320\277\320\270\321\201\320\260"
+  "\320\273 \321\215\321\202\320\276 \320\277\321\200\320\270\320\273\320\276"
+  "\320\266\320\265\320\275\320\270\320\265.\n"
+  "\n"
+  "\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
+  "\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
+  "\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
+  "\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
+  "\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
+  "\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
+  "\320\265.",
+};
+
+
+const char *
+verified_cert_text[LI_COUNT] = {
+  // eng
+  "This Panda3D application has been signed by %s.  "
+  "If you trust %s, then click the Run button below "
+  "to run this application on your computer.  This will also "
+  "automatically approve this and any other applications signed by "
+  "%s in the future.\n"
+  "\n"
+  "If you are unsure about this application, "
+  "you should click Cancel instead.",
+
+  // nld
+  "Deze Panda3D applicatie is ondertekend door %s.  "
+  "Als u %s vertrouwt, klik dan de onderstaande knop Uitvoeren om de applicatie "
+  "op uw computer uit te voeren.  Dit zal ook deze en andere door %s getekende "
+  "applicaties in het vervolg toestaan.\n"
+  "\n"
+  "Als u niet zeker bent over deze applicatie is het aanbevolen om op "
+  "Annuleren te klikken.",
+
+  // deu
+  "Diese Panda3D-Anwendung wurde von %s signiert.  Falls Sie %s vertrauen, "
+  "dr\303\274cken Sie den Starten-Knopf, um diese Anwendung auszuf\303\274hren.  "
+  "Zudem werden in der Zukunft diese und alle anderen von %s signierten "
+  "Anwendungen automatisch als vertrauensw\303\274rdig anerkannt.\n"
+  "\n"
+  "Falls Sie sich unsicher \303\274ber diese Anwendung sind, sollten Sie "
+  "Abbrechen dr\303\274cken.",
+
+  // spa
+  "Esta aplicaci\303\263n de Panda3D ha sido firmada por %s.  Si se considera %s"
+  "de confianza el bot\303\263n inferior ejecutar\303\241 la aplicaci\303\263n."
+  "Esto validara esta y cualquier otra applizacion firmada por %s en el futuro.\n"
+  "\n"
+  "Si se duda de la aplicaci\303\263nse recomienda cancelar."
+
+  // ita
+  "Questa applicazione Panda3D \303\250 stata firmata da %s.  Se %s \303\250 "
+  "un'entit\303\240 fidata, allora clicca il bottone Lancia sottostante per "
+  "lanciare questa applicazione sul tuo computer. Inoltre, ci\303\262 "
+  "approver\303\240 automaticamente questa e ogni altra applicazione "
+  "firmata da %s in futuro.\n"
+  "\n"
+  "Se non sei sicuro circa questa applicazione, dovresti invece cliccare "
+  "su Cancella.",
+
+  // epo
+  "\304\210i tiu aplika\304\265o estas subskribita de %s.  "
+  "Se %s estas fidinda la\305\255 vi, premu la butonon 'Lan\304\211i' sube por "
+  "lan\304\211i \304\211i tiun aplika\304\265on per via komputilo.  Anka\305\255 "
+  "tio a\305\255tomate estonece aprobos \304\211i tiun kaj alian ajn "
+  "aplika\304\265on, kiu estas subskribita de %s.\n"
+  "\n"
+  "Se vi ne estas certa pri \304\211i tiu aplika\304\265o, "
+  "vi anstata\305\255e povus premi la butonon 'Nuligi'.",
+
+  // rus
+  "\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
+  "\320\265\320\275\320\270\320\265 \320\277\320\276\320\264\320\277\320\270"
+  "\321\201\320\260\320\275\320\276 %s.  "
+  "\320\225\321\201\320\273\320\270 \320\262\321\213 \320\264\320\276\320\262"
+  "\320\265\321\200\321\217\320\265\321\202\320\265 %s, \320\275\320\260"
+  "\320\266\320\274\320\270\321\202\320\265 \320\272\320\275\320\276\320\277"
+  "\320\272\321\203 \"\320\227\320\260\320\277\321\203\321\201\321\202"
+  "\320\270\321\202\321\214\" \320\262\320\275\320\270\320\267\321\203, "
+  "\321\207\321\202\320\276\320\261\321\213 \320\267\320\260\320\277\321\203"
+  "\321\201\321\202\320\270\321\202\321\214 \321\215\321\202\320\276 \320\277"
+  "\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265 "
+  "\320\275\320\260 \320\262\320\260\321\210\320\265\320\274 \320\272\320\276"
+  "\320\274\320\277\321\214\321\216\321\202\320\265\321\200\320\265. \320\255"
+  "\321\202\320\276 \321\202\320\260\320\272\320\266\320\265 \320\260\320\262"
+  "\321\202\320\276\320\274\320\260\321\202\320\270\321\207\320\265\321\201"
+  "\320\272\320\270 \320\277\320\276\320\264\321\202\320\262\320\265\321\200"
+  "\320\264\320\270\321\202 \321\215\321\202\320\276 \320\270 \320\264"
+  "\321\200\321\203\320\263\320\270\320\265 \320\277\321\200\320\270\320\273"
+  "\320\276\320\266\320\265\320\275\320\270\321\217, \320\275\320\260\320\277"
+  "\320\270\321\201\320\260\320\275\320\275\321\213\320\265 %s \320\262 "
+  "\320\261\321\203\320\264\321\203\321\211\320\265\320\274.\n"
+  "\n"
+  "\320\225\321\201\320\273\320\270 \320\262\321\213 \320\275\320\265 "
+  "\321\203\320\262\320\265\321\200\320\265\320\275\321\213 \320\262 \321\215"
+  "\321\202\320\276\320\274 \320\277\321\200\320\270\320\273\320\276\320\266"
+  "\320\265\320\275\320\270\320\270, \320\275\320\260\320\266\320\274\320\270"
+  "\321\202\320\265 \320\272\320\275\320\276\320\277\320\272\321\203 \""
+  "\320\236\321\202\320\274\320\265\320\275\320\260\".",
+};
+
+
+const char *
+expired_cert_text[LI_COUNT] = {
+  // eng
+  "This Panda3D application has been signed by %s, "
+  "but the certificate has expired.\n"
+  "\n"
+  "You should check the current date set on your computer's clock "
+  "to make sure it is correct.\n"
+  "\n"
+  "If your computer's date is correct, we recommend "
+  "you click Cancel to avoid running this application.",
+
+  // nld
+  "Deze Panda3D applicatie is ondertekend door %s, maar de geldigheidsdatum "
+  "van het certificaat is verstreken.\n"
+  "\n"
+  "Controleer de datum op uw computerklok om te zorgen dat deze juist is "
+  "ingesteld.\n"
+  "\n"
+  "Als de datum op uw computer juist is, is het aanbevolen om op Annuleren te "
+  "klikken om de applicatie af te sluiten.",
+
+  // deu
+  "Diese Anwendung wurde von %s signiert, aber das Zertifikat ist abgelaufen.\n"
+  "\n"
+  "Sie sollten die aktuelle Uhrzeit auf Ihrem Computer "
+  "\303\274berpr\303\274fen, um sicherzugehen, dass sie korrekt ist.\n"
+  "\n"
+  "Falls die Uhrzeit auf Ihrem Computer korrekt ist, empfehlen wir Ihnen "
+  "Abbrechen zu dr\303\274cken.",
+
+  // spa
+  "Esta aplicaci\303\263n Panda3D ha sido firmada por %s pero el certificado ha"
+  "caducado.\n"
+  "\n"
+  "Se recomienda comprobar la fecha del reloj.\n"
+  "\n"
+  "Si la fecha del reloj es correcta se recomienda cancelar.",
+
+  // ita
+  "Questa applicazione Panda3D \303\250 stata firmata da %s, ma il "
+  "certificato \303\250 scaduto.\n"
+  "\n"
+  "Dovresti controllare la data attuale impostata nell'orologio del tuo "
+  "computer per assicurarti che sia corretta.\n"
+  "\n"
+  "Se la data del tuo computer \303\250 corretta, raccomandiamo di cliccare "
+  "Cancella per evitare di lanciare questa applicazione."
+
+  // epo
+  "\304\210i tiu aplika\304\265o de Panda3D estas subskribita de %s, "
+  "sed la atesto eksvalidi\304\235is.\n"
+  "\n"
+  "Vi povus kontroli la aktualan daton, kiu estas agordata sur la horlo\304\235o de "
+  "via komputilo por certigi ke \304\235i estas korekta.\n"
+  "\n"
+  "Se la dato de via komputilo estas korekta, ni rekomendas ke vi premas la "
+  "butonon 'Nuligi' por eviti lan\304\211on de \304\211i tiu aplika\304\265o.",
+
+  // rus
+  "\320\255\321\202\320\276 \320\277\321\200\320\270\320\273\320\276\320\266"
+  "\320\265\320\275\320\270\320\265 \320\277\320\276\320\264\320\277\320\270"
+  "\321\201\320\260\320\275\320\276 %s, \320\276\320\264\320\275\320\260"
+  "\320\272\320\276 \321\201\321\200\320\276\320\272 \320\264\320\265\320\271"
+  "\321\201\321\202\320\262\320\270\321\217 \321\201\320\265\321\200\321\202"
+  "\320\270\321\204\320\270\320\272\320\260\321\202\320\260 \320\270\321\201"
+  "\321\202\321\221\320\272.\n"
+  "\n"
+  "\320\237\321\200\320\276\320\262\320\265\321\200\321\214\321\202\320\265, "
+  "\320\277\320\276\320\266\320\260\320\273\321\203\320\271\321\201\321\202"
+  "\320\260, \320\264\320\260\321\202\321\203 \320\275\320\260 \320\262"
+  "\320\260\321\210\320\265\320\274 \320\272\320\276\320\274\320\277\321\214"
+  "\321\216\321\202\320\265\321\200\320\265.\n"
+  "\n"
+  "\320\225\321\201\320\273\320\270 \320\275\320\260 \320\262\320\260\321\210"
+  "\320\265\320\274 \320\272\320\276\320\274\320\277\321\214\321\216\321\202"
+  "\320\265\321\200\320\265 \321\203\321\201\321\202\320\260\320\275\320\276"
+  "\320\262\320\273\320\265\320\275\320\276 \320\277\321\200\320\260\320\262"
+  "\320\270\320\273\321\214\320\275\320\276\320\265 \320\262\321\200\320\265"
+  "\320\274\321\217, \320\274\321\213 \321\200\320\265\320\272\320\276"
+  "\320\274\320\265\320\275\320\264\321\203\320\265\320\274 \320\262\320\260"
+  "\320\274 \320\275\320\260\320\266\320\260\321\202\321\214 \320\272\320\275"
+  "\320\276\320\277\320\272\321\203 \"\320\236\321\202\320\274\320\265"
+  "\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
+  "\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
+  "\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
+  "\320\265.",
+};
+
+
+const char *
+generic_error_cert_text[LI_COUNT] = {
+  // eng
+  "This Panda3D application has been signed, but there is a problem "
+  "with the certificate (OpenSSL error code %d).\n"
+  "\n"
+  "We recommend you click Cancel to avoid running this application.",
+
+  // nld
+  "Deze Panda3D applicatie is ondertekend, maar er is een probleem "
+  "met het certificaat opgetreden (OpenSSL foutcode %d).\n"
+  "\n"
+  "Het is aanbevolen om op Annuleren te klikken om de applicatie af te "
+  "sluiten.",
+
+  // deu
+  "Diese Panda3D-Anwendung wurde signiert, aber es gibt ein Problem mit "
+  "dem Zertifikat (OpenSSL Fehlercode %d).\n"
+  "\n"
+  "Wir empfehlen, dass Sie Abbrechen dr\303\274cken um diese Anwendung nicht "
+  "auszuf\303\274hren.",
+
+  // spa
+  "Esta aplicaci\303\263n de Panda3D esta firmada pero hay un problema con el "
+  "certificado (Error de OpenSSL %d).\n"
+  "\n"
+  "Se recomienda cancelar para evitar ejecutar esta aplicaci\303\263n.",
+
+  // ita
+  "Questa applicazione Panda3D \303\250 stata firmata, ma c'\303\250 un "
+  "problema col certificato (codice di errore OpenSSL %s).\n"
+  "\n"
+  "Raccomandiamo di cliccare su Cancella per evitare di lanciare questa "
+  "applicazione.",
+
+  // epo
+  "\304\210i tiu aplika\304\265o de Panda3D estas subskribita, sed la "
+  "atesto havas problemon (OpenSSL erarkodo %d).\n"
+  "\n"
+  "Ni rekomendas ke vi premas la butonon 'Nuligi' por eviti lan\304\211on "
+  "de \304\211i tiu aplika\304\265o.",
+
+  // rus
+  "\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
+  "\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\265\321\201"
+  "\321\202\321\214 \320\277\320\276\320\264\320\277\320\270\321\201\321\214,"
+  " \320\275\320\276 \320\262\320\276\320\267\320\275\320\270\320\272\320\273"
+  "\320\260 \320\277\321\200\320\276\320\261\320\273\320\265\320\274\320\260 "
+  "\321\201 \321\201\320\265\321\200\321\202\320\270\321\204\320\270\320\272"
+  "\320\260\321\202\320\276\320\274 (\320\232\320\276\320\264 \320\276"
+  "\321\210\320\270\320\261\320\272\320\270 OpenSSL %d).\n"
+  "\n"
+  "\320\234\321\213 \321\200\320\265\320\272\320\276\320\274\320\265\320\275"
+  "\320\264\321\203\320\265\320\274 \320\262\320\260\320\274 \320\275\320\260"
+  "\320\266\320\260\321\202\321\214 \"\320\236\321\202\320\274\320\265"
+  "\320\275\320\260\" \320\270 \320\275\320\265 \320\267\320\260\320\277"
+  "\321\203\321\201\320\272\320\260\321\202\321\214 \321\215\321\202\320\276 "
+  "\320\277\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270"
+  "\320\265.",
+};
+
+
+const char *
+no_cert_text[LI_COUNT] = {
+  "This Panda3D application has not been signed.  This means you have "
+  "no way of knowing for sure who wrote it.\n"
+  "\n"
+  "Click Cancel to avoid running this application.",
+
+  // nld
+  "Deze Panda3D applicatie is niet ondertekend.  Dit betekent dat het niet "
+  "mogelijk is om de auteur te verifi\303\253ren.\n"
+  "\n"
+  "Klik op Annuleren om de applicatie af te sluiten.",
+
+  // deu
+  "Diese Panda3D-Anwendung wurde nicht signiert.  Es gibt keine "
+  "M\303\266glichkeit festzustellen, wer diese entwickelt hat.\n"
+  "\n"
+  "Dr\303\274cken Sie Abbrechen, um diese Anwendung nicht auszuf\303\274hren.",
+
+  // spa
+  "Esta aplicaci\303\263n de Panda3D no esta firmada, no hay forma de conocer "
+  "quien la ha escrito.\n"
+  "\n"
+  "Cancelar para evitar ejecutar la aplicaci\303\263n.",
+
+  // ita
+  "Questa applicazione Panda3D non \303\250 stata firmata.  Ci\303\262 "
+  "significa che non hai modo di assicurarti circa chi la abbia scritta.\n"
+  "\n"
+  "Clicca Cancella per evitare di lanciare questa applicazione.",
+
+  // epo
+  "\304\210i tiu aplika\304\265o de Panda3D ne estas subskribita.  Tio "
+  "signifas ke vi ne havas certan scimanieron pri la vera verkanto de "
+  "la aplika\304\265o.\n"
+  "\n"
+  "Premu la butonon 'Nuligi' por eviti lan\304\211on de \304\211i tiu "
+  "aplika\304\265o.",
+
+  // rus
+  "\320\243 \321\215\321\202\320\276\320\263\320\276 \320\277\321\200\320\270"
+  "\320\273\320\276\320\266\320\265\320\275\320\270\321\217 \320\275\320\265"
+  "\321\202 \320\277\320\276\320\264\320\277\320\270\321\201\320\270. "
+  "\320\255\321\202\320\276 \320\276\320\267\320\275\320\260\321\207\320\260"
+  "\320\265\321\202, \321\207\321\202\320\276 \320\262\321\213 \320\275"
+  "\320\265 \320\274\320\276\320\266\320\265\321\202\320\265 \320\267\320\275"
+  "\320\260\321\202\321\214, \320\272\321\202\320\276 \320\265\320\263"
+  "\320\276 \320\275\320\260\320\277\320\270\321\201\320\260\320\273.\n"
+  "\n"
+  "\320\235\320\260\320\266\320\274\320\270\321\202\320\265 \"\320\236"
+  "\321\202\320\274\320\265\320\275\320\260\", \321\207\321\202\320\276"
+  "\320\261\321\213 \320\275\320\265 \320\267\320\260\320\277\321\203\321\201"
+  "\320\272\320\260\321\202\321\214 \320\277\321\200\320\270\320\273\320\276"
+  "\320\266\320\265\320\275\320\270\320\265.",
+};

+ 45 - 0
direct/src/plugin/p3dCert_strings.h

@@ -0,0 +1,45 @@
+// Filename: p3dCert_strings.h
+// Created by:  rdb (25Mar15)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+enum LanguageIndex {
+  LI_en, // English
+  LI_nl, // Dutch
+  LI_de, // German
+  LI_es, // Spanish
+  LI_it, // Italian
+  LI_eo, // Esperanto
+  LI_ru, // Russian
+  LI_COUNT,
+
+  LI_default = LI_en
+};
+
+extern const char *language_codes[LI_COUNT];
+extern const unsigned char language_ids[LI_COUNT];
+
+extern const char *run_title[LI_COUNT];
+extern const char *cancel_title[LI_COUNT];
+extern const char *show_cert_title[LI_COUNT];
+
+extern const char *new_application_title[LI_COUNT];
+extern const char *no_cert_title[LI_COUNT];
+extern const char *unverified_cert_title[LI_COUNT];
+extern const char *expired_cert_title[LI_COUNT];
+
+extern const char *self_signed_cert_text[LI_COUNT];
+extern const char *unknown_auth_cert_text[LI_COUNT];
+extern const char *verified_cert_text[LI_COUNT];
+extern const char *expired_cert_text[LI_COUNT];
+extern const char *generic_error_cert_text[LI_COUNT];
+extern const char *no_cert_text[LI_COUNT];

+ 3 - 1
direct/src/plugin/p3dSession.cxx

@@ -891,11 +891,13 @@ start_p3dpython(P3DInstance *inst) {
     // These are the enviroment variables we forward from the current
     // environment, if they are set.
     const char *keep[] = {
-      "HOME", "USER", 
+      "HOME", "USER",
 #ifdef _WIN32
       "SYSTEMROOT", "USERPROFILE", "COMSPEC",
       "SYSTEMDRIVE", "ALLUSERSPROFILE", "APPDATA", "COMMONPROGRAMFILES",
       "PROGRAMFILES", "WINDIR", "PROGRAMDATA", "USERDOMAIN",
+#else
+      "LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG",
 #endif
 #ifdef HAVE_X11
       "DISPLAY", "XAUTHORITY",

+ 2 - 0
makepanda/makepanda.py

@@ -5055,9 +5055,11 @@ if (RTDIST or RUNTIME):
     if (PkgSkip("FLTK")==0):
       OPTS.append("FLTK")
       TargetAdd('plugin_p3dCert.obj', opts=OPTS, input='p3dCert.cxx')
+      TargetAdd('plugin_p3dCert_strings.obj', opts=OPTS, input='p3dCert_strings.cxx')
       TargetAdd('p3dcert.exe', input='plugin_mkdir_complete.obj')
       TargetAdd('p3dcert.exe', input='plugin_wstring_encode.obj')
       TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj')
+      TargetAdd('p3dcert.exe', input='plugin_p3dCert_strings.obj')
       OPTS=['OPENSSL', 'FLTK', 'X11', 'WINCOMCTL', 'WINSOCK', 'WINGDI', 'WINUSER', 'ADVAPI', 'WINOLE', 'WINSHELL', 'SUBSYSTEM:WINDOWS']
       if GetTarget() == 'darwin':
           OPTS += ['OPT:2']