1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   Internat.h
6 
7   Markus Meyer
8   Dominic Mazzoni (Mac OS X code)
9 
10 **********************************************************************/
11 
12 #ifndef __AUDACITY_INTERNAT__
13 #define __AUDACITY_INTERNAT__
14 
15 #include <vector>
16 #include <wx/longlong.h>
17 
18 #include "TranslatableString.h"
19 
20 class wxArrayString;
21 class wxArrayStringEx;
22 
23 extern STRINGS_API const wxString& GetCustomTranslation(const wxString& str1 );
24 extern STRINGS_API const wxString& GetCustomSubstitution(const wxString& str1 );
25 
26 // Marks string for substitution only.
27 #define _TS( s ) GetCustomSubstitution( s )
28 
29 // Marks strings for extraction only... use .Translate() to translate.
30 // '&', preceding menu accelerators, should NOT occur in the argument.
31 #define XO(s)  (TranslatableString{ wxT(s), {} })
32 
33 // Alternative taking a second context argument.  A context is a string literal,
34 // which is not translated, but serves to disambiguate uses of the first string
35 // that might need differing translations, such as "Light" meaning not-heavy in
36 // one place but not-dark elsewhere.
37 #define XC(s, c)  (TranslatableString{ wxT(s), {} }.Context(c))
38 
39 // Marks strings for extraction only, where '&', preceding menu accelerators, MAY
40 // occur.
41 // For now, expands exactly as macro XO does, but in future there will be a
42 // type distinction - for example XXO should be used for menu item names that
43 // might use the & character for shortcuts.
44 #define XXO(s)  XO(s)
45 
46 // Corresponds to XC as XXO does to XO
47 #define XXC(s, c) XC(s, c)
48 
49 #ifdef _
50    #undef _
51 #endif
52 
53 #if defined( _DEBUG )
54    // Force a crash if you misuse _ in a static initializer, so that translation
55    // is looked up too early and not found.
56 
57    #ifdef __WXMSW__
58 
59    // Eventually pulls in <windows.h> which indirectly defines DebugBreak(). Can't
60    // include <windows.h> directly since it then causes "MemoryX.h" to spew errors.
61    #include <wx/app.h>
62    #define _(s) ((wxTranslations::Get() || (DebugBreak(), true)), \
63                 GetCustomTranslation((s)))
64 
65    #else
66 
67    #include <signal.h>
68    // Raise a signal because it's even too early to use wxASSERT for this.
69    #define _(s) ((wxTranslations::Get() || raise(SIGTRAP)), \
70                 GetCustomTranslation((s)))
71 
72    #endif
73 
74 #else
75    #define _(s) GetCustomTranslation((s))
76 #endif
77 
78 #ifdef XP
79    #undef XP
80 #endif
81 
82 
83 // The two string arguments will go to the .pot file, as
84 // msgid sing
85 // msgid_plural plural
86 //
87 // (You must use plain string literals.  Do not use _() or wxT() or L prefix,
88 //  which (intentionally) will fail to compile.  The macro inserts wxT).
89 //
90 // Note too:  The i18n-hint comment must be on the line preceding the first
91 // string.  That might be inside the parentheses of the macro call.
92 //
93 // The macro call is then followed by a sequence of format arguments in
94 // parentheses.  The third argument of the macro call is the zero-based index
95 // of the format argument that selects singular or plural
96 #define XP(sing, plur, n) \
97    TranslatableString{ wxT(sing), {} }.Plural<(n)>( wxT(plur) )
98 
99 // Like XP but with an additional context argument, as for XC
100 #define XPC(sing, plur, n, c) \
101    TranslatableString{ wxT(sing), {} }.Context(c).Plural<(n)>( wxT(plur) )
102 
103 class STRINGS_API Internat
104 {
105 public:
106    /** \brief Initialize internationalisation support. Call this once at
107     * program start. */
108    static void Init();
109 
110    /** \brief Get the decimal separator for the current locale.
111     *
112     * Normally, this is a decimal point ('.'), but e.g. Germany uses a
113     * comma (',').*/
114    static wxChar GetDecimalSeparator();
115    static void SetCeeNumberFormat();
116 
117    /** \brief Convert a string to a number.
118     *
119     * This function will accept BOTH point and comma as a decimal separator,
120     * regardless of the current locale.
121     * Returns 'true' on success, and 'false' if an error occurs. */
122    static bool CompatibleToDouble(const wxString& stringToConvert, double* result);
123 
124    // Function version of above.
125    static double CompatibleToDouble(const wxString& stringToConvert);
126 
127    /** \brief Convert a number to a string, always uses the dot as decimal
128     * separator*/
129    static wxString ToString(double numberToConvert,
130                      int digitsAfterDecimalPoint = -1);
131 
132    /** \brief Convert a number to a string, uses the user's locale's decimal
133     * separator */
134    static wxString ToDisplayString(double numberToConvert,
135                      int digitsAfterDecimalPoint = -1);
136 
137    /** \brief Convert a number to a string while formatting it in bytes, KB,
138     * MB, GB */
139    static TranslatableString FormatSize(wxLongLong size);
140    static TranslatableString FormatSize(double size);
141 
142    /** \brief Check a proposed file name string for illegal characters and
143     * remove them
144     * return true iff name is "visibly" changed (not necessarily equivalent to
145     * character-wise changed)
146     */
147    static bool SanitiseFilename(wxString &name, const wxString &sub);
148 
GetExcludedCharacters()149    static const wxArrayString &GetExcludedCharacters()
150    { return exclude; }
151 
152 private:
153    static wxChar mDecimalSeparator;
154 
155    static wxArrayString exclude;
156 };
157 
158 // Convert C strings to wxString
159 #define UTF8CTOWX(X) wxString((X), wxConvUTF8)
160 #define LAT1CTOWX(X) wxString((X), wxConvISO8859_1)
161 
162 // Whether disambiguationg contexts are supported
163 // If not, then the program builds and runs, but strings in the catalog with
164 // contexts will fail to translate
165 #define HAS_I18N_CONTEXTS wxCHECK_VERSION(3, 1, 1)
166 
167 #endif
168