Mercurial > repos > IBBoard
annotate Lang/Translation.cs @ 71:40c09e57d213
Fixes #31: Break out Translations for language to own class
* Make Translation class use new extracted class objects
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Tue, 06 Apr 2010 18:08:43 +0000 |
parents | b5d7e8b93205 |
children | 091bfa54d6c7 |
rev | line source |
---|---|
16 | 1 // This file (Translation.cs) is a part of the IBBoard library and is copyright 2009 IBBoard. |
2 // | |
3 // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license. | |
4 | |
37 | 5 using System; |
6 using System.IO; | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
7 using System.Xml; |
37 | 8 using System.Xml.Schema; |
9 using System.Collections.Generic; | |
10 using System.Reflection; | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
11 using System.ComponentModel; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
12 using IBBoard.IO; |
37 | 13 using IBBoard.Logging; |
14 using IBBoard.Xml; | |
15 | |
16 namespace IBBoard.Lang | |
17 { | |
18 /// <summary> | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
19 /// A basic string translator that a specified language and returns translated strings that correspond to translation IDs. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
20 /// If the string doesn't exist in the specified language then the translator falls back defined 'super' languages. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
21 /// If the translation doesn't exist in the hierarchy of languages then either a supplied value, null or a "no validation available" |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
22 /// message is returned, depending on the parameters supplied to the method. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
23 /// |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
24 /// Loaded languages are referenced by two-character language code (e.g. "en" or "it") |
37 | 25 /// </summary> |
26 public class Translation | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
27 { |
37 | 28 private static readonly string DIVIDER_STRING = "-"; |
29 private static DirectoryInfo translationDir; | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
30 private static AbstractTranslationSet translations; |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
31 private static TranslationXmlLoader loader; |
6 | 32 |
33 /// <summary> | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
34 /// Initialises the translations and loads the specified language so that the Translation class can be used. |
21
c8d74202182a
Closes #14 - Throw specific exceptions from translations
IBBoard <dev@ibboard.co.uk>
parents:
16
diff
changeset
|
35 /// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can |
c8d74202182a
Closes #14 - Throw specific exceptions from translations
IBBoard <dev@ibboard.co.uk>
parents:
16
diff
changeset
|
36 /// still be called but no translation will be performed. |
6 | 37 /// </summary> |
38 /// <param name="appPath"> | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
39 /// The full path that the contains the "translations" folder - normally the application directory path. |
6 | 40 /// </param> |
41 /// <param name="language"> | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
42 /// The language to use as the loaded language |
37 | 43 /// </param> |
44 public static void InitialiseTranslations(string appPath, string language) | |
6 | 45 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
46 InitialiseTranslations(appPath); |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
47 LoadTranslationForLanguage(language); |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
48 } |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
49 |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
50 /// <summary> |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
51 /// Initialises the translation class for an application or source. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
52 /// </summary> |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
53 /// <param name="appPath"> |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
54 /// The full path that the contains the "translations" folder - normally the application directory path. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
55 /// </param> |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
56 public static void InitialiseTranslations(string appPath) |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
57 { |
6 | 58 InitialiseDefaults(appPath); |
59 } | |
60 | |
61 private static void InitialiseDefaults(string appPath) | |
62 { | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
63 string translationPath = Path.Combine(appPath, "translations"); |
37 | 64 |
65 if (Directory.Exists(translationPath)) | |
6 | 66 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
67 translations = null; |
37 | 68 translationDir = new DirectoryInfo(translationPath); |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
69 loader = new TranslationXmlLoader(Path.Combine(appPath, "schemas/translation.xsd")); |
37 | 70 } |
71 else | |
72 { | |
69
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
73 throw new TranslationLoadException("Translation path not found ("+new FileInfo(translationPath).FullName+")"); |
6 | 74 } |
75 } | |
76 | |
22
ea058f9ea9d4
Closes #15 - Migrate to schema for translations
IBBoard <dev@ibboard.co.uk>
parents:
21
diff
changeset
|
77 /// <summary> |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
78 /// Resets the loaded translations and reverts to no translations. |
69
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
79 /// </summary> |
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
80 public static void Reset() |
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
81 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
82 translations = null; |
69
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
83 } |
6 | 84 |
85 /// <summary> | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
86 /// Loads translations for a given language and sets them as the current language. |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
87 /// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can |
21
c8d74202182a
Closes #14 - Throw specific exceptions from translations
IBBoard <dev@ibboard.co.uk>
parents:
16
diff
changeset
|
88 /// still be called but all translations will fall back to the default translation. |
6 | 89 /// </summary> |
90 /// <param name="translationLang"> | |
91 /// The new local language to load | |
37 | 92 /// </param> |
93 public static void LoadTranslation(string translationLanguage) | |
7
f4da31cb09d9
* Add translation DTD to utils project
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
94 { |
f4da31cb09d9
* Add translation DTD to utils project
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
95 if (translationLanguage == "" || translationLanguage == null) |
6 | 96 { |
10
3b7a321e7c4c
Fixes #4 - unexpected exception in translations
IBBoard <dev@ibboard.co.uk>
parents:
9
diff
changeset
|
97 throw new ArgumentException("Translation language cannot be null or empty"); |
37 | 98 } |
99 | |
100 LoadTranslationForLanguage(translationLanguage); | |
7
f4da31cb09d9
* Add translation DTD to utils project
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
101 } |
f4da31cb09d9
* Add translation DTD to utils project
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
102 |
f4da31cb09d9
* Add translation DTD to utils project
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
103 private static void LoadTranslationForLanguage(string translationLanguage) |
67
5fb2e5a2e7a8
* Remove errors on uninitialised translations - means that the translations just fall back to the provided string if they haven't been initialised
IBBoard <dev@ibboard.co.uk>
parents:
65
diff
changeset
|
104 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
105 if (translationLanguage != "" && translationLanguage != null) |
37 | 106 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
107 translations = loader.LoadTranslations(GetTranslationFile(translationLanguage)); |
6 | 108 } |
109 else | |
110 { | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
111 translations = null; |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
112 } |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
113 } |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
114 |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
115 private static string GetTranslationFile(string language) |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
116 { |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
117 string translationFileName = language + ".translation"; |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
118 string path = Path.Combine(translationDir.FullName, translationFileName); |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
119 |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
120 if (!File.Exists(path)) |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
121 { |
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
122 throw new TranslationLoadException(translationFileName +" could not be found in "+translationDir.FullName); |
6 | 123 } |
37 | 124 |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
125 return path; |
37 | 126 } |
6 | 127 |
128 /// <summary> | |
129 /// Gets a translation for a given ID, falling back to a "missing translation" message if none can be found. Also optionally replaces any placeholders with the supplied values. | |
130 /// </summary> | |
131 /// <param name="translationID"> | |
132 /// The ID to look up the translation for | |
133 /// </param> | |
134 /// <param name="replacements"> | |
135 /// A collection of <see cref="System.Object"/>s to replace placeholders with | |
136 /// </param> | |
137 /// <returns> | |
138 /// The translation with the placeholders replaced or a "missing translation" message | |
37 | 139 /// </returns> |
140 public static string GetTranslation(string translationID, params object[] replacements) | |
141 { | |
142 return GetTranslation(translationID, false, replacements); | |
143 } | |
6 | 144 |
145 /// <summary> | |
146 /// Gets a translation for a given ID, falling back to null or a warning message if a translation cannot be found. Also optionally replaces any placeholders with the supplied values. | |
147 /// </summary> | |
148 /// <param name="translationID"> | |
149 /// The ID to look up the translation for | |
150 /// </param> | |
151 /// <param name="returnNullOnFail"> | |
152 /// TRUE if null should be returned when no translation can be found, or FALSE if a "missing translation" message should be returned | |
153 /// </param> | |
154 /// <param name="replacements"> | |
155 /// A collection of <see cref="System.Object"/>s to replace placeholders with | |
156 /// </param> | |
157 /// <returns> | |
158 /// The translation with the placeholders replaced, or a "missing translation" message or null depending on <param name="returnNullOnFail"> | |
37 | 159 /// </returns> |
160 public static string GetTranslation(string translationID, bool returnNullOnFail, params object[] replacements) | |
161 { | |
162 return GetTranslation(translationID, returnNullOnFail ? null : "", replacements); | |
163 } | |
6 | 164 |
165 /// <summary> | |
166 /// Gets a translation for a given ID, falling back to a supplied default if a translation cannot be found. Also optionally replaces any placeholders with the supplied values. | |
167 /// </summary> | |
168 /// <param name="translationID"> | |
169 /// The ID to look up the translation for | |
170 /// </param> | |
171 /// <param name="defaultTranslation"> | |
172 /// The string to return if no translation can be found. Can be null or any string. | |
173 /// </param> | |
174 /// <param name="replacements"> | |
175 /// A collection of <see cref="System.Object"/>s to replace placeholders with | |
176 /// </param> | |
177 /// <returns> | |
178 /// The translation, if one exists, or the supplied default with the placeholders replaced | |
37 | 179 /// </returns> |
180 public static string GetTranslation(string translationID, string defaultTranslation, params object[] replacements) | |
181 { | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
182 string trans = GetTranslationFromTranslationSet(translationID); |
37 | 183 |
184 if (trans == null) | |
185 { | |
186 trans = GetDefaultTranslation(translationID, defaultTranslation); | |
187 } | |
188 | |
189 trans = AddVariablesToTranslation(trans, replacements); | |
190 | |
191 return trans; | |
6 | 192 } |
193 | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
194 private static string GetTranslationFromTranslationSet(string translationID) |
6 | 195 { |
196 string translation = null; | |
197 | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
198 if (translations!=null) |
37 | 199 { |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
200 translation = translations[translationID]; |
6 | 201 } |
202 | |
203 return translation; | |
204 } | |
205 | |
206 private static string GetDefaultTranslation(string translationID, string defaultTranslation) | |
207 { | |
69
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
208 return (defaultTranslation != "" || defaultTranslation == null) ? defaultTranslation : GetMissingTranslationMessage(translationID); |
37 | 209 } |
6 | 210 |
211 private static string GetMissingTranslationMessage(string translationID) | |
212 { | |
213 return "++ Missing Translation "+translationID+" ++"; | |
214 } | |
215 | |
216 private static string AddVariablesToTranslation(string translation, object[] replacements) | |
217 { | |
37 | 218 if (translation != null && replacements != null && replacements.Length > 0) |
219 { | |
220 translation = String.Format(translation, replacements); | |
6 | 221 } |
222 | |
223 return translation; | |
224 } | |
225 | |
226 /// <summary> | |
36
c949727ec0e0
Re #22 - Make failing control translation cleaner for normal use
IBBoard <dev@ibboard.co.uk>
parents:
35
diff
changeset
|
227 /// Translate an <see cref="ITranslatable"/> item, with optional string replacement. If the translation |
c949727ec0e0
Re #22 - Make failing control translation cleaner for normal use
IBBoard <dev@ibboard.co.uk>
parents:
35
diff
changeset
|
228 /// does not exist then a warning message will be used as the translated text. |
6 | 229 /// </summary> |
230 /// <param name="item"> | |
231 /// A <see cref="ITranslatable"/> to set the text for | |
232 /// </param> | |
233 /// <param name="replacements"> | |
234 /// A collection of <see cref="System.Object"/>s that will be used to fill place-holders | |
37 | 235 /// </param> |
236 public static void Translate(ITranslatable item, params object[] replacements) | |
237 { | |
69
b5d7e8b93205
Re #30: Improve Translations API
IBBoard <dev@ibboard.co.uk>
parents:
67
diff
changeset
|
238 Translate(item, GetMissingTranslationMessage(item.Name), replacements); |
37 | 239 } |
240 | |
241 /// <summary> | |
242 /// Translate an <see cref="ITranslatable"/> item, with optional string replacement. The <code>defaultText</code> | |
243 /// can be used to specify an alternate translation. Passing <code>null</code> will result in a warning message | |
244 /// about a missing translation ID. | |
245 /// </summary> | |
246 /// <param name="item"> | |
247 /// A <see cref="ITranslatable"/> to set the text for | |
248 /// </param> | |
249 /// <param name="defaultText"> | |
250 /// The default string to display if no translation could be found. | |
251 /// </param> | |
252 /// <param name="replacements"> | |
253 /// A collection of <see cref="System.Object"/>s that will be used to fill place-holders | |
254 /// </param> | |
255 public static void Translate(ITranslatable item, string defaultText, params object[] replacements) | |
256 { | |
257 if (item.Text == "" || item.Text == DIVIDER_STRING) | |
258 { | |
259 //it doesn't need translating - either there is no text from the developer or it's a hyphen for a divider | |
260 return; | |
261 } | |
262 | |
263 item.Text = GetTranslation(item.Name, defaultText, replacements); | |
6 | 264 } |
265 | |
266 /// <summary> | |
267 /// Get the current local translation language. This is an arbitrary string used in the translation file's name and will not necessarily match the ISO language code. | |
268 /// </summary> | |
269 /// <returns> | |
270 /// The string used in the file name of the current local translation | |
271 /// </returns> | |
272 public static string GetTranslationLanguage() | |
273 { | |
71
40c09e57d213
Fixes #31: Break out Translations for language to own class
IBBoard <dev@ibboard.co.uk>
parents:
69
diff
changeset
|
274 return (translations!=null ? translations.LanguageCode : ""); |
37 | 275 } |
276 } | |
277 } |