PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/GitUI/FormTranslate.cs

https://github.com/eisnerd/gitextensions
C# | 633 lines | 536 code | 91 blank | 6 comment | 116 complexity | e4376e826de79ea953996a47a9afb655 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Windows.Forms;
  9. using ResourceManager;
  10. using ResourceManager.Translation;
  11. namespace GitUI
  12. {
  13. public partial class FormTranslate : GitExtensionsForm
  14. {
  15. //TranslationStrings
  16. readonly TranslationString translateProgressText = new TranslationString("Translated {0} out of {1}");
  17. readonly TranslationString allText = new TranslationString("All");
  18. readonly TranslationString saveCurrentChangesText = new TranslationString("Do you want to save the current changes?");
  19. readonly TranslationString saveCurrentChangesCaption = new TranslationString("Save changes");
  20. readonly TranslationString saveAsText = new TranslationString("Save as");
  21. readonly TranslationString saveAsTextFilter = new TranslationString("Translation file (*.xml)");
  22. readonly TranslationString selectLanguageCode = new TranslationString("Select a language code first.");
  23. readonly TranslationString noLanguageCodeSelected = new TranslationString("There is no languagecode selected." +
  24. Environment.NewLine + "Do you want to select a language code first?");
  25. readonly TranslationString noLanguageCodeSelectedCaption = new TranslationString("Language code");
  26. readonly TranslationString editingCellPrefixText = new TranslationString("[EDITING]");
  27. [DebuggerDisplay("{DebuggerDisplay,nq}")]
  28. public class TranslateItem : INotifyPropertyChanged
  29. {
  30. public string Category { get; set; }
  31. public string Name { get; set; }
  32. public string Property { get; set; }
  33. public string NeutralValue { get; set; }
  34. private string _translatedValue;
  35. public string TranslatedValue
  36. {
  37. get { return _translatedValue; }
  38. set
  39. {
  40. var pc = PropertyChanged;
  41. if (pc != null)
  42. {
  43. pc(this, new PropertyChangedEventArgs("TranslatedValue"));
  44. }
  45. _translatedValue = value;
  46. }
  47. }
  48. public TranslationType Status { get; set; }
  49. public event PropertyChangedEventHandler PropertyChanged;
  50. private string DebuggerDisplay
  51. {
  52. get { return string.Format("\"{0}\" - \"{1}\"{2}", Category, NeutralValue,
  53. Status == TranslationType.Translated ? "" : " " + Status.ToString()); }
  54. }
  55. }
  56. private List<TranslateItem> translate;
  57. readonly Translation neutralTranslation = new Translation();
  58. Translation translation;
  59. private TranslationCategory allCategories = new TranslationCategory();
  60. private bool changesMade;
  61. public FormTranslate()
  62. {
  63. InitializeComponent(); Translate();
  64. translations.Items.Clear();
  65. translations.Sorted = true;
  66. translations.Items.AddRange(Translator.GetAllTranslations());
  67. GetPropertiesToTranslate();
  68. LoadTranslation();
  69. translateCategories.SelectedItem = allCategories;
  70. FillTranslateGrid(allCategories);
  71. foreach (CultureInfo cultureInfo in CultureInfo.GetCultures(CultureTypes.AllCultures))
  72. {
  73. if (!_NO_TRANSLATE_languageCode.Items.Contains(cultureInfo.TwoLetterISOLanguageName))
  74. {
  75. _NO_TRANSLATE_languageCode.Items.Add(string.Concat(cultureInfo.TwoLetterISOLanguageName, " (", cultureInfo.DisplayName, ")"));
  76. }
  77. }
  78. FormClosing += FormTranslate_FormClosing;
  79. }
  80. private void FormTranslate_Load(object sender, EventArgs e)
  81. {
  82. RestorePosition("translate");
  83. }
  84. void FormTranslate_FormClosing(object sender, FormClosingEventArgs e)
  85. {
  86. AskForSave();
  87. SavePosition("translate");
  88. }
  89. private void UpdateProgress()
  90. {
  91. int translatedCount = translate.Count(translateItem => !string.IsNullOrEmpty(translateItem.TranslatedValue));
  92. var progresMsg = string.Format(translateProgressText.Text, translatedCount.ToString(), translate.Count.ToString());
  93. if (translateProgress.Text != progresMsg)
  94. {
  95. translateProgress.Text = progresMsg;
  96. toolStrip1.Refresh();
  97. }
  98. }
  99. private bool CompareSourceString(string origin, string current)
  100. {
  101. bool equal = (origin == current);
  102. if (!equal)
  103. return origin == current.Replace("\n", Environment.NewLine);
  104. return equal;
  105. }
  106. private void LoadTranslation()
  107. {
  108. translate = new List<TranslateItem>();
  109. var neutralItems =
  110. from translationCategory in neutralTranslation.GetTranslationCategories()
  111. from translationItem in translationCategory.GetTranslationItems()
  112. select new
  113. {
  114. Category = translationCategory.Name,
  115. Name = translationItem.Name,
  116. Property = translationItem.Property,
  117. Source = translationItem.Source,
  118. Value = translationItem.Value
  119. };
  120. var translationItems = translation != null ?
  121. (from translationCategory in translation.GetTranslationCategories()
  122. from translationItem in translationCategory.GetTranslationItems()
  123. select new
  124. {
  125. Category = translationCategory.Name,
  126. Name = translationItem.Name,
  127. Property = translationItem.Property,
  128. Source = translationItem.Source,
  129. Value = translationItem.Value
  130. }).ToList() : null;
  131. Dictionary<string, string> dict = new Dictionary<string, string>();
  132. foreach (var item in neutralItems)
  133. {
  134. var translateItem = new TranslateItem
  135. {
  136. Category = item.Category,
  137. Name = item.Name,
  138. Property = item.Property,
  139. NeutralValue = item.Value,
  140. Status = TranslationType.New
  141. };
  142. if (translation != null)
  143. {
  144. var curItem =
  145. (from trItem in translationItems
  146. where trItem.Category.TrimStart('_') == item.Category.TrimStart('_') &&
  147. trItem.Name.TrimStart('_') == item.Name.TrimStart('_') &&
  148. trItem.Property == item.Property
  149. select trItem).FirstOrDefault();
  150. if (curItem != null)
  151. {
  152. translateItem.TranslatedValue = curItem.Value;
  153. if (curItem.Source == null || CompareSourceString(item.Value, curItem.Source))
  154. {
  155. if (!String.IsNullOrEmpty(curItem.Value))
  156. translateItem.Status = TranslationType.Translated;
  157. else
  158. translateItem.Status = TranslationType.Unfinished;
  159. }
  160. else
  161. translateItem.Status = TranslationType.Obsolete;
  162. translationItems.Remove(curItem);
  163. string source = curItem.Source ?? item.Value;
  164. if (!String.IsNullOrEmpty(curItem.Value) && !dict.ContainsKey(source))
  165. dict.Add(source, curItem.Value);
  166. }
  167. }
  168. translate.Add(translateItem);
  169. }
  170. if (translationItems != null)
  171. {
  172. foreach (var item in translationItems)
  173. {
  174. if (!String.IsNullOrEmpty(item.Value))
  175. {
  176. var translateItem = new TranslateItem
  177. {
  178. Category = item.Category,
  179. Name = item.Name,
  180. Property = item.Property,
  181. NeutralValue = item.Source,
  182. TranslatedValue = item.Value,
  183. Status = TranslationType.Obsolete
  184. };
  185. translate.Add(translateItem);
  186. if (item.Source != null && !dict.ContainsKey(item.Source))
  187. dict.Add(item.Source, item.Value);
  188. }
  189. }
  190. }
  191. var untranlatedItems = from trItem in translate
  192. where trItem.Status == TranslationType.New &&
  193. dict.ContainsKey(trItem.NeutralValue)
  194. select trItem;
  195. foreach (var untranlatedItem in untranlatedItems)
  196. {
  197. untranlatedItem.Status = TranslationType.Unfinished;
  198. untranlatedItem.TranslatedValue = dict[untranlatedItem.NeutralValue];
  199. }
  200. UpdateProgress();
  201. }
  202. private void FillTranslateGrid(TranslationCategory filter)
  203. {
  204. if (translate == null)
  205. return;
  206. translateItemBindingSource.DataSource = null;
  207. var filterTranslate = translate.Where(translateItem => filter == null || filter == allCategories || filter.Name.Equals(translateItem.Category)).Where(translateItem => !hideTranslatedItems.Checked || string.IsNullOrEmpty(translateItem.TranslatedValue)).ToList();
  208. translateItemBindingSource.DataSource = filterTranslate;
  209. UpdateProgress();
  210. }
  211. private bool IsAssemblyTranslatable(Assembly assembly)
  212. {
  213. if ((assembly.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)) ||
  214. (assembly.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase)) ||
  215. (assembly.FullName.StartsWith("Presentation", StringComparison.OrdinalIgnoreCase)) ||
  216. (assembly.FullName.StartsWith("WindowsBase", StringComparison.OrdinalIgnoreCase)) ||
  217. (assembly.FullName.StartsWith("ICSharpCode", StringComparison.OrdinalIgnoreCase)) ||
  218. (assembly.FullName.StartsWith("access", StringComparison.OrdinalIgnoreCase)) ||
  219. (assembly.FullName.StartsWith("SMDiag", StringComparison.OrdinalIgnoreCase)) ||
  220. (assembly.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase)) ||
  221. (assembly.FullName.StartsWith("vshost", StringComparison.OrdinalIgnoreCase)))
  222. {
  223. return false;
  224. }
  225. return true;
  226. }
  227. private List<Type> GetTranslatableTypes()
  228. {
  229. List<Type> translatableTypes = new List<Type>();
  230. foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
  231. {
  232. if (IsAssemblyTranslatable(assembly))
  233. {
  234. foreach (Type type in assembly.GetTypes())
  235. {
  236. if (type.IsClass && typeof(ITranslate).IsAssignableFrom(type))
  237. {
  238. translatableTypes.Add(type);
  239. }
  240. }
  241. }
  242. }
  243. return translatableTypes;
  244. }
  245. private object CreateInstanceOfClass(Type type)
  246. {
  247. BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
  248. object obj = null;
  249. if (type == GetType())
  250. obj = this;
  251. else
  252. {
  253. // try to find parameter less constructor first
  254. foreach (ConstructorInfo constructor in type.GetConstructors(flags))
  255. {
  256. if (constructor.GetParameters().Length == 0)
  257. obj = Activator.CreateInstance(type, true);
  258. }
  259. }
  260. if (obj == null && type.GetConstructors().Length > 0)
  261. {
  262. ConstructorInfo parameterConstructor = type.GetConstructors(flags)[0];
  263. var parameters = new List<object>(parameterConstructor.GetParameters().Length);
  264. for (int i = 0; i < parameterConstructor.GetParameters().Length; i++)
  265. parameters.Add(null);
  266. obj = parameterConstructor.Invoke(parameters.ToArray());
  267. }
  268. Debug.Assert(obj != null);
  269. return obj;
  270. }
  271. public void GetPropertiesToTranslate()
  272. {
  273. translateCategories.Items.Clear();
  274. allCategories.Name = allText.Text;
  275. translateCategories.Items.Add(allCategories);
  276. string currentTranslation = GitCommands.Settings.Translation;
  277. try
  278. {
  279. //Set language to neutral to get neutral translations
  280. GitCommands.Settings.Translation = "";
  281. List<Type> translatableTypes = GetTranslatableTypes();
  282. foreach (Type type in translatableTypes)
  283. {
  284. ITranslate obj = CreateInstanceOfClass(type) as ITranslate;
  285. if (obj != null)
  286. obj.AddTranslationItems(neutralTranslation);
  287. }
  288. }
  289. finally
  290. {
  291. neutralTranslation.Sort();
  292. translateCategories.Items.AddRange(neutralTranslation.GetTranslationCategories().ToArray());
  293. //Restore translation
  294. GitCommands.Settings.Translation = currentTranslation;
  295. }
  296. }
  297. private void translateCategories_SelectedIndexChanged(object sender, EventArgs e)
  298. {
  299. FillTranslateGrid(translateCategories.SelectedItem as TranslationCategory);
  300. }
  301. private void saveAs_Click(object sender, EventArgs e)
  302. {
  303. if (string.IsNullOrEmpty(_NO_TRANSLATE_languageCode.Text))
  304. if (MessageBox.Show(this, noLanguageCodeSelected.Text, noLanguageCodeSelectedCaption.Text, MessageBoxButtons.YesNo) == DialogResult.Yes)
  305. return;
  306. toolStrip1.Select();
  307. SaveAs();
  308. }
  309. private string GetSelectedLanguageCode()
  310. {
  311. if (string.IsNullOrEmpty(_NO_TRANSLATE_languageCode.Text) || _NO_TRANSLATE_languageCode.Text.Length < 2)
  312. return null;
  313. return _NO_TRANSLATE_languageCode.Text.Substring(0, 2);
  314. }
  315. private void SaveAs()
  316. {
  317. var foreignTranslation = new Translation { LanguageCode = GetSelectedLanguageCode() };
  318. foreach (TranslateItem translateItem in translate)
  319. {
  320. string value = translateItem.TranslatedValue ?? String.Empty;
  321. TranslationItem ti = new TranslationItem(translateItem.Name, translateItem.Property,
  322. translateItem.NeutralValue, value);
  323. ti.Status = translateItem.Status;
  324. if (ti.Status == TranslationType.Obsolete &&
  325. (String.IsNullOrEmpty(value) || String.IsNullOrEmpty(translateItem.NeutralValue)))
  326. continue;
  327. if (string.IsNullOrEmpty(value))
  328. {
  329. if (ti.Status == TranslationType.Translated || ti.Status == TranslationType.New)
  330. ti.Status = TranslationType.Unfinished;
  331. }
  332. else
  333. {
  334. // TODO: Support in form
  335. if (ti.Status == TranslationType.Unfinished)
  336. ti.Status = TranslationType.Translated;
  337. }
  338. foreignTranslation.FindOrAddTranslationCategory(translateItem.Category).AddTranslationItem(ti);
  339. }
  340. var fileDialog =
  341. new SaveFileDialog
  342. {
  343. Title = saveAsText.Text,
  344. FileName = translations.Text + ".xml",
  345. Filter = saveAsTextFilter.Text + "|*.xml",
  346. DefaultExt = ".xml",
  347. AddExtension = true
  348. };
  349. if (fileDialog.ShowDialog(this) == DialogResult.OK)
  350. {
  351. TranslationSerializer.Serialize(foreignTranslation, fileDialog.FileName);
  352. changesMade = false;
  353. }
  354. }
  355. private void translations_SelectedIndexChanged(object sender, EventArgs e)
  356. {
  357. AskForSave();
  358. changesMade = false;
  359. translation = Translator.GetTranslation(translations.Text);
  360. LoadTranslation();
  361. FillTranslateGrid(translateCategories.SelectedItem as TranslationCategory);
  362. if (translation == null)
  363. {
  364. _NO_TRANSLATE_languageCode.Text = "";
  365. return;
  366. }
  367. try
  368. {
  369. var culture = new CultureInfo(translation.LanguageCode);
  370. _NO_TRANSLATE_languageCode.Text = string.Concat(culture.TwoLetterISOLanguageName, " (", culture.DisplayName, ")");
  371. }
  372. catch
  373. {
  374. _NO_TRANSLATE_languageCode.Text = translation.LanguageCode;
  375. }
  376. }
  377. private void hideTranslatedItems_CheckedChanged(object sender, EventArgs e)
  378. {
  379. FillTranslateGrid(translateCategories.SelectedItem as TranslationCategory);
  380. }
  381. private void AskForSave()
  382. {
  383. if (changesMade)
  384. {
  385. if (MessageBox.Show(this, saveCurrentChangesText.Text, saveCurrentChangesCaption.Text, MessageBoxButtons.YesNo) == DialogResult.Yes)
  386. {
  387. SaveAs();
  388. }
  389. }
  390. }
  391. private void translateGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
  392. {
  393. changesMade = true;
  394. UpdateProgress();
  395. }
  396. private void toolStripButton1_CheckedChanged(object sender, EventArgs e)
  397. {
  398. splitContainer2.Panel2Collapsed = _toolStripButton1.Checked;
  399. }
  400. private void translatedText_TextChanged(object sender, EventArgs e)
  401. {
  402. if (translateGrid.SelectedRows.Count == 1)
  403. {
  404. changesMade = true;
  405. UpdateProgress();
  406. }
  407. }
  408. TranslateItem translateItemInEditing;
  409. private void translatedText_Enter(object sender, System.EventArgs e)
  410. {
  411. if (translateItemInEditing != null)
  412. {
  413. translateItemInEditing.TranslatedValue = translatedText.Text;
  414. }
  415. translateItemInEditing = (TranslateItem)translateItemBindingSource.Current;
  416. if (translateItemInEditing != null)
  417. {
  418. translateItemInEditing.TranslatedValue = editingCellPrefixText.Text + " " + translateItemInEditing.TranslatedValue;
  419. }
  420. }
  421. private void translatedText_Leave(object sender, System.EventArgs e)
  422. {
  423. //Debug.Assert(translateItemInEditing != null);
  424. if (translateItemInEditing != null)
  425. {
  426. translateItemInEditing.TranslatedValue = translatedText.Text;
  427. translateItemInEditing = null;
  428. }
  429. }
  430. private void translateGrid_Click(object sender, EventArgs e)
  431. {
  432. if (translateGrid.SelectedRows.Count == 1)
  433. {
  434. if (_toolStripButton1.Checked)
  435. {
  436. splitContainer2.Panel2Collapsed = false;
  437. }
  438. var translateItem = (TranslateItem)translateGrid.SelectedRows[0].DataBoundItem;
  439. if (translateItem == null) return;
  440. neutralTekst.Text = translateItem.NeutralValue;
  441. translatedText.Text = translateItem.TranslatedValue;
  442. }
  443. else
  444. {
  445. splitContainer2.Panel2Collapsed = true;
  446. }
  447. }
  448. private void translateGrid_SelectionChanged(object sender, EventArgs e)
  449. {
  450. bool nowTranslatedTextInEditing = translateItemInEditing != null;
  451. translatedText_Leave(null, null);
  452. translateGrid_Click(null, null);
  453. if (nowTranslatedTextInEditing)
  454. {
  455. translatedText_Enter(null, null);
  456. }
  457. }
  458. private void nextButton_Click(object sender, EventArgs e)
  459. {
  460. if (translateGrid.SelectedRows.Count == 1)
  461. {
  462. if (translateGrid.CurrentCell.RowIndex < translateGrid.Rows.Count - 1)
  463. translateItemBindingSource.MoveNext();
  464. }
  465. else
  466. if (translateGrid.Rows.Count > 0)
  467. {
  468. translateGrid.Rows[0].Selected = true;
  469. }
  470. }
  471. private void previousButton_Click(object sender, EventArgs e)
  472. {
  473. if (translateGrid.SelectedRows.Count == 1)
  474. {
  475. if (translateGrid.CurrentCell.RowIndex > 0)
  476. translateItemBindingSource.MovePrevious();
  477. }
  478. else
  479. if (translateGrid.Rows.Count > 0)
  480. {
  481. translateGrid.Rows[0].Selected = true;
  482. }
  483. }
  484. private void googleTranslate_Click(object sender, EventArgs e)
  485. {
  486. if (string.IsNullOrEmpty(_NO_TRANSLATE_languageCode.Text))
  487. {
  488. MessageBox.Show(this, selectLanguageCode.Text);
  489. return;
  490. }
  491. if (translateGrid.SelectedRows.Count == 1)
  492. {
  493. var translateItem = ((TranslateItem)translateGrid.SelectedRows[0].DataBoundItem);
  494. translateItem.TranslatedValue = Google.TranslateText(translateItem.NeutralValue, "en", GetSelectedLanguageCode());
  495. translateGrid_Click(null, null);
  496. translateGrid.Refresh();
  497. }
  498. }
  499. private void googleAll_Click(object sender, EventArgs e)
  500. {
  501. if (string.IsNullOrEmpty(_NO_TRANSLATE_languageCode.Text))
  502. {
  503. MessageBox.Show(this, selectLanguageCode.Text);
  504. return;
  505. }
  506. foreach (TranslateItem translateItem in translate)
  507. {
  508. if (string.IsNullOrEmpty(translateItem.TranslatedValue))
  509. translateItem.TranslatedValue = Google.TranslateText(translateItem.NeutralValue, "en", GetSelectedLanguageCode());
  510. UpdateProgress();
  511. translateGrid.Refresh();
  512. }
  513. translateGrid_Click(null, null);
  514. }
  515. private void toolStripButtonNew_Click(object sender, EventArgs e)
  516. {
  517. translations.Text = "";
  518. translations_SelectedIndexChanged(null, null);
  519. }
  520. private void translatedText_KeyDown(object sender, KeyEventArgs e)
  521. {
  522. if (e.Alt && e.KeyCode == Keys.Up)
  523. {
  524. e.Handled = true;
  525. previousButton_Click(sender, e);
  526. }
  527. else if (e.Alt && e.KeyCode == Keys.Down ||
  528. e.Control && e.KeyCode == Keys.Enter)
  529. {
  530. e.Handled = true;
  531. nextButton_Click(sender, e);
  532. }
  533. else if (e.Control && e.KeyCode == Keys.Down)
  534. {
  535. e.Handled = true;
  536. translatedText.SelectionStart = 0;
  537. translatedText.SelectionLength = translatedText.TextLength;
  538. translatedText.SelectedText = neutralTekst.Text;
  539. }
  540. }
  541. }
  542. }