mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[pollock] add automatic PO generation and update detection
* Also use Rufus application version in .loc
This commit is contained in:
parent
af9cca5fb3
commit
d9d0feadb6
5 changed files with 563 additions and 213 deletions
|
@ -12,6 +12,7 @@ skip_commits:
|
|||
- '**/*.cmd'
|
||||
- '**/*.cs'
|
||||
- '**/*.md'
|
||||
- '**/*.rc'
|
||||
- '**/*.sh'
|
||||
- '**/*.txt'
|
||||
- '**/*.xml'
|
||||
|
|
|
@ -15,13 +15,13 @@ content. PLEASE, do not just look at this Changelog when updating your
|
|||
translation, but always use the English section of rufus.loc as your base.
|
||||
For instance, MSG_114, that was introduced in v1.0.8 is MORE than one line!
|
||||
|
||||
o Version 1.0.24 (2018.??.??)
|
||||
o v3.2 (2018.??.??)
|
||||
- *NEW* MSG_087
|
||||
- *NEW* MSG_172
|
||||
- *NEW* MSG_199
|
||||
- *NEW* MSG_306
|
||||
|
||||
o Version 1.0.23 (2018.03.27)
|
||||
o v3.0 (2018.03.27)
|
||||
- All positioning ('m', 's') has now been removed as well as some controls, for the 3.0 UI redesign
|
||||
- *NEW* IDS_DRIVE_PROPERTIES_TXT "Drive Properties"
|
||||
- *NEW* IDS_BOOT_SELECTION_TXT "Boot selection"
|
||||
|
@ -73,7 +73,7 @@ o Version 1.0.23 (2018.03.27)
|
|||
for the languages who did that. This means that "Save Log", "Clear Log" "Close Log" have become "Save", "Clear", "Close".
|
||||
*PLEASE* verify that the modification looks correct in your language.
|
||||
|
||||
o Version 1.0.22 (2017.07.17)
|
||||
o v2.16 (2017.07.17)
|
||||
- *NEW* MSG_295 "Warning: Unofficial version"
|
||||
- *NEW* MSG_296 "This version of Rufus was NOT produced by its official developer(s).\n\nAre you sure you want to run it?"
|
||||
- *NEW* MSG_297 "Truncated ISO detected"
|
||||
|
@ -82,7 +82,7 @@ o Version 1.0.22 (2017.07.17)
|
|||
"official ones.\n\nNote that you can compute the MD5 or SHA in Rufus by clicking the '#' button."
|
||||
Note: You can test MSG_297/MSG_298 using https://rufus.akeo.ie/testing/arch_trunc.iso (A truncated version of archlinux-2017.07.01-x86_64.iso)
|
||||
|
||||
o Version 1.0.21 (2017.01.16)
|
||||
o v2.12 (2017.01.16)
|
||||
- *NEW* MSG_288 "Missing elevated privileges"
|
||||
- *NEW* MSG_289 "This application can only run with elevated privileges"
|
||||
This message, along with the previous, is just to notify the user when they have
|
||||
|
@ -104,7 +104,7 @@ o Version 1.0.21 (2017.01.16)
|
|||
- *NEW* MSG_294 "This version of Windows is no longer supported by Rufus."
|
||||
These two messages are not used anywhere yet, but may be needed in a future prompt.
|
||||
|
||||
o Version 1.0.20 (2016.05.09)
|
||||
o v2.9 (2016.05.09)
|
||||
- *NEW* MSG_286 "Zeroing drive: %0.1f%% completed"
|
||||
Used when filling a whole drive with zero bytes, to display progress in percent (e.g. "Zeroing drive: 12.3% completed")
|
||||
Can be tested with Alt-Z (CAUTION: THIS WILL COMPLETELY ERASE THE SELECTED DRIVE!!)
|
||||
|
@ -112,7 +112,7 @@ o Version 1.0.20 (2016.05.09)
|
|||
Note, this message is followed by either "enabled"/"disabled" (see MSG_250/251) and is similar to MSG_253
|
||||
The message appears on the status bar and can be tested with Ctrl-Alt-F.
|
||||
|
||||
o Version 1.0.19 (2015.10.15)
|
||||
o v2.5 (2015.10.15)
|
||||
Note: The following message can be tested by pressing Alt-, (That's the 'Alt' and 'comma' keys on your keyboard)
|
||||
In case the message below is not clear, you can consider that it says "Exclusive locking of the USB drive"
|
||||
- *NEW* MSG_282 "Exclusive USB drive locking"
|
||||
|
@ -123,7 +123,7 @@ o Version 1.0.19 (2015.10.15)
|
|||
- *NEW* MSG_285 "The downloaded executable is signed by '%s'.\nThis is not a signature we recognize and could "
|
||||
"indicate some form of malicious activity...\nAre you sure you want to run this file?"
|
||||
|
||||
o Version 1.0.18 (2015.09.03)
|
||||
o v2.4 (2015.09.03)
|
||||
- Changed MSG_081 "Unsupported ISO" -> "Unsupported image"
|
||||
- Changed MSG_082 -> "This image is either non-bootable, or it uses a boot or compression method that is not supported by Rufus..."
|
||||
- *NEW* MSG_269 "Preserve timestamps"
|
||||
|
@ -148,7 +148,7 @@ o Version 1.0.18 (2015.09.03)
|
|||
- *NEW* MSG_280 "Image selection"
|
||||
- *NEW* MSG_281 "(Please select an image)"
|
||||
|
||||
o Version 1.0.17 (2015.02.04)
|
||||
o v2.0 (2015.02.04)
|
||||
- *NEW CONTROL* IDC_WINDOWS_INSTALL "Standard Windows installation" (Main dialog)
|
||||
- *NEW CONTROL* IDC_WINDOWS_TO_GO "Windows To Go" (Main dialog)
|
||||
Note: to see the 2 controls above displayed, you will need to load the "Windows To Go.iso" image from
|
||||
|
|
|
@ -20,9 +20,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -58,6 +61,25 @@ namespace pollock
|
|||
this.group = group;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Id o = obj as Id;
|
||||
|
||||
return (o.group == this.group) && (o.id == this.id);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (this.group + ":" + this.id).GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (this.group == "MSG")
|
||||
return this.id;
|
||||
return this.group + " → " + this.id;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Language
|
||||
|
@ -67,20 +89,23 @@ namespace pollock
|
|||
public string version;
|
||||
public string lcid;
|
||||
public SortedDictionary<string, List<Message>> sections;
|
||||
public Dictionary<string, string> comments;
|
||||
public Dictionary<Id, string> comments;
|
||||
public Dictionary<Id, string> id_to_str;
|
||||
public Language()
|
||||
{
|
||||
sections = new SortedDictionary<string, List<Message>>();
|
||||
comments = new Dictionary<string, string>();
|
||||
comments = new Dictionary<Id, string>();
|
||||
id_to_str = new Dictionary<Id, string>();
|
||||
}
|
||||
}
|
||||
|
||||
class Pollock
|
||||
{
|
||||
private static string app_name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
|
||||
private static string app_version = "v"
|
||||
+ Assembly.GetEntryAssembly().GetName().Version.Major.ToString() + "."
|
||||
+ Assembly.GetEntryAssembly().GetName().Version.Minor.ToString();
|
||||
private static string app_name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Assembly.GetExecutingAssembly().GetName().Name);
|
||||
private static int[] version = new int[2]
|
||||
{ Assembly.GetEntryAssembly().GetName().Version.Major, Assembly.GetEntryAssembly().GetName().Version.Minor };
|
||||
private static string version_str = "v" + version[0].ToString() + "." + version[1].ToString();
|
||||
private static string app_path = AppDomain.CurrentDomain.BaseDirectory;
|
||||
private static bool cancel_requested = false;
|
||||
private const string LANG_ID = "Language";
|
||||
private const string LANG_NAME = "X-Rufus-LanguageName";
|
||||
|
@ -88,35 +113,41 @@ namespace pollock
|
|||
private const string LANG_LCID = "X-Rufus-LCID";
|
||||
private static Encoding encoding = new UTF8Encoding(false);
|
||||
private static List<string> rtl_languages = new List<string> { "ar-SA", "he-IL", "fa-IR" };
|
||||
private static System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
||||
private static Stopwatch sw = new System.Diagnostics.Stopwatch();
|
||||
private static WebClient wc = new WebClient();
|
||||
private static DateTime last_changed = DateTime.MinValue;
|
||||
private static int download_status;
|
||||
private static int console_x_pos;
|
||||
private static bool in_progress = false;
|
||||
private static bool in_on_change = false;
|
||||
private static double speed = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Wait for a key to be pressed.
|
||||
/// </summary>
|
||||
static void WaitForKey()
|
||||
static void WaitForKey(string msg = null)
|
||||
{
|
||||
if (msg == null)
|
||||
msg = "Press any key to continue...";
|
||||
// Flush the input buffer
|
||||
while (Console.KeyAvailable)
|
||||
Console.ReadKey(true);
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine("Press any key to exit...");
|
||||
Console.WriteLine(msg);
|
||||
Console.ReadKey(true);
|
||||
while (Console.KeyAvailable)
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import languages from an existing rufus.loc
|
||||
/// Import languages from an existing Rufus loc file
|
||||
/// </summary>
|
||||
/// <param name="path">The directy where the loc file is located.</param>
|
||||
/// <param name="file">The name of the loc file.</param>
|
||||
/// <param name="select_id">(Optional) If specified, only the language with this id, along with en-US will be returned.</param>
|
||||
/// <returns>A list of Language elements.</returns>
|
||||
static List<Language> ParseLocFile(string path, string id = null)
|
||||
static List<Language> ParseLocFile(string file, string select_id = null)
|
||||
{
|
||||
var rufus_loc = path + @"\rufus.loc";
|
||||
var rufus_pot = path + @"\rufus.pot";
|
||||
var lines = File.ReadAllLines(rufus_loc);
|
||||
var lines = File.ReadAllLines(file);
|
||||
int line_nr = 0;
|
||||
string format = "D" + (int)(Math.Log10((double)lines.Count()) + 0.99999);
|
||||
string last_key = null;
|
||||
|
@ -126,24 +157,24 @@ namespace pollock
|
|||
List<Language> langs = new List<Language>();
|
||||
Language lang = null;
|
||||
bool skip_line = false;
|
||||
bool found_my_id = false;
|
||||
Id id;
|
||||
|
||||
sw.Start();
|
||||
|
||||
if (!File.Exists(rufus_loc))
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
Console.Error.WriteLine($"Could not open {rufus_loc}");
|
||||
Console.Error.WriteLine($"Could not open {file}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Importing data from '{rufus_loc}':");
|
||||
Console.Write($"Importing data from '{file}'... ");
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (cancel_requested)
|
||||
if ((cancel_requested) || (found_my_id && skip_line))
|
||||
break;
|
||||
++line_nr;
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
Console.Write($"[{line_nr.ToString(format)}/{lines.Count()}] ");
|
||||
//Console.SetCursorPosition(0, Console.CursorTop);
|
||||
//Console.Write($"[{line_nr.ToString(format)}/{lines.Count()}] ");
|
||||
var data = line.Trim();
|
||||
int i = data.IndexOf("#");
|
||||
if (i > 0)
|
||||
|
@ -171,13 +202,17 @@ namespace pollock
|
|||
Console.WriteLine("Error: Invalid 'l' command");
|
||||
return null;
|
||||
}
|
||||
string lid = parts[1].Replace("\"", "");
|
||||
if (id != null)
|
||||
string cur_id = parts[1].Replace("\"", "");
|
||||
if (select_id != null)
|
||||
{
|
||||
if ((!skip_line) && (id != lid) && (lid != "en-US"))
|
||||
if ((select_id == "en-US") && (cur_id != "en-US"))
|
||||
skip_line = true;
|
||||
else if (skip_line && (id == lid))
|
||||
else if ((!skip_line) && (select_id != cur_id) && (cur_id != "en-US"))
|
||||
skip_line = true;
|
||||
else if (skip_line && (select_id == cur_id))
|
||||
skip_line = false;
|
||||
if (select_id == cur_id)
|
||||
found_my_id = true;
|
||||
if (skip_line)
|
||||
break;
|
||||
}
|
||||
|
@ -186,7 +221,7 @@ namespace pollock
|
|||
lang = new Language();
|
||||
lang.id = parts[1].Replace("\"", "");
|
||||
lang.name = parts[2].Replace("\"", "");
|
||||
Console.WriteLine($"Found language {lang.id} '{lang.name}'");
|
||||
//Console.WriteLine($"Found language {lang.id} '{lang.name}'");
|
||||
lang.lcid = parts[3];
|
||||
for (i = 4; i < parts.Count; i++)
|
||||
lang.lcid += " " + parts[i];
|
||||
|
@ -223,10 +258,14 @@ namespace pollock
|
|||
continue;
|
||||
}
|
||||
lang.sections[section_name].Add(new Message(parts[1], parts[2]));
|
||||
// We also maintain global list of Id -> str for convenience
|
||||
// TODO: This lookup BREAKS on multiline!!
|
||||
lang.id_to_str.Add(new Id(section_name, (parts[1])), parts[2]);
|
||||
last_key = parts[1];
|
||||
if (comment != null)
|
||||
{
|
||||
lang.comments[last_key] = comment.Trim();
|
||||
id = new Id(section_name, last_key);
|
||||
lang.comments[id] = comment.Trim();
|
||||
comment = null;
|
||||
}
|
||||
break;
|
||||
|
@ -238,16 +277,16 @@ namespace pollock
|
|||
}
|
||||
lang.sections[section_name].Last().str += data;
|
||||
lang.sections[section_name].Last().str = lang.sections[section_name].Last().str.Replace("\"\"", "");
|
||||
id = new Id(section_name, last_key);
|
||||
lang.id_to_str[id] += data;
|
||||
lang.id_to_str[id] = lang.id_to_str[id].Replace("\"\"", "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lang != null)
|
||||
langs.Add(lang);
|
||||
|
||||
sw.Stop();
|
||||
Console.WriteLine($"{(cancel_requested ? "CANCELLED after" : "DONE in")}" +
|
||||
$" {sw.ElapsedMilliseconds / 1000.0}s.");
|
||||
sw.Reset();
|
||||
Console.WriteLine(cancel_requested ? "CANCELLED" : "DONE");
|
||||
|
||||
return langs;
|
||||
}
|
||||
|
@ -255,37 +294,67 @@ namespace pollock
|
|||
/// <summary>
|
||||
/// Create .po/.pot files from a list of Language elements.
|
||||
/// </summary>
|
||||
/// <param name="path">The path where the .po/.pot files should be created.</param>
|
||||
/// <param name="langs">A lits of Languages elements</param>
|
||||
/// <returns>true on success, false on error.</returns>
|
||||
static bool CreatePoFiles(string path, List<Language> langs, bool merge_pot = false)
|
||||
/// <param name="langs">A lits of Language objects to process.</param>
|
||||
/// <param name="old_en_US">(Optional) A previous version of en-US to use for comparison.</param>
|
||||
/// <param name="path">(Optional) The path where the .po/.pot files should be created.</param>
|
||||
/// <returns>The number of PO files created.</returns>
|
||||
static int CreatePoFiles(List<Language> langs, Language old_en_US = null, string path = null)
|
||||
{
|
||||
if (langs == null)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
var en_US = langs.Find(x => x.id == "en-US");
|
||||
if (en_US == null)
|
||||
return false;
|
||||
var cur_en_US = langs.Find(x => x.id == "en-US");
|
||||
if (cur_en_US == null)
|
||||
return 0;
|
||||
|
||||
var msg_to_ids = new Dictionary<string, List<Id>>();
|
||||
if (path == null)
|
||||
path = app_path;
|
||||
if (!path.EndsWith("\\"))
|
||||
path += '\\';
|
||||
|
||||
// Build a dictionary of message string to List<Id> so that we can identify duplicates and remove them
|
||||
foreach (var section in en_US.sections)
|
||||
// Build the list of all the current IDs we need to process
|
||||
var en_ids = new List<Id>();
|
||||
foreach (var kvp in cur_en_US.id_to_str)
|
||||
en_ids.Add(new Id(kvp.Key.group, kvp.Key.id));
|
||||
|
||||
var added_ids = new List<Id>();
|
||||
var modified_ids = new List<Id>();
|
||||
|
||||
if (old_en_US != null)
|
||||
{
|
||||
foreach (var msg in section.Value)
|
||||
foreach (var id in cur_en_US.id_to_str.Keys)
|
||||
{
|
||||
if (msg_to_ids.ContainsKey(msg.str))
|
||||
msg_to_ids[msg.str].Add(new Id(section.Key, msg.id));
|
||||
else
|
||||
msg_to_ids.Add(msg.str, new List<Id>() { new Id(section.Key, msg.id) });
|
||||
if (!old_en_US.id_to_str.ContainsKey(id))
|
||||
{
|
||||
// ID is not present in old -> added
|
||||
//Console.WriteLine($"ADDED: {id} = {cur_en_US.id_to_str[id]}");
|
||||
added_ids.Add(id);
|
||||
}
|
||||
else if (old_en_US.id_to_str[id] != cur_en_US.id_to_str[id])
|
||||
{
|
||||
// Ignore messages where we just removed the trailing \n
|
||||
if (!old_en_US.id_to_str[id].EndsWith("\\n\""))
|
||||
{
|
||||
// ID exists in both but str has changed -> modified
|
||||
//Console.WriteLine($"MODIFIED: {id} = {old_en_US.id_to_str[id]} → {cur_en_US.id_to_str[id]}");
|
||||
modified_ids.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nb_po_saved = 0;
|
||||
foreach (var lang in langs)
|
||||
{
|
||||
bool is_pot = (lang.id == "en-US");
|
||||
var target = path + @"\" + (is_pot ? "rufus.pot" : lang.id + ".po");
|
||||
Console.WriteLine($"Creating '{target}'");
|
||||
// Don't create the .pot if we are producing a merge
|
||||
if (is_pot && old_en_US != null)
|
||||
continue;
|
||||
var target = path + (is_pot ? "rufus.pot" : lang.id + ".po");
|
||||
if (old_en_US != null)
|
||||
Console.Write($"Computing differences and creating '{target}'... ");
|
||||
else
|
||||
Console.Write($"Creating '{target}'... ");
|
||||
|
||||
using (var writer = new StreamWriter(target, false, encoding))
|
||||
{
|
||||
|
@ -311,50 +380,59 @@ namespace pollock
|
|||
|
||||
var dupes = new List<string>();
|
||||
|
||||
foreach (var section in lang.sections)
|
||||
foreach(var id in en_ids)
|
||||
{
|
||||
foreach (var msg in section.Value)
|
||||
var en_str = cur_en_US.sections[id.group].Find(x => x.id == id.id).str;
|
||||
// Handle duplicate IDs
|
||||
if (dupes.Contains(en_str))
|
||||
continue;
|
||||
|
||||
writer.WriteLine();
|
||||
|
||||
var cid_list = cur_en_US.id_to_str.Where(x => x.Value == en_str).Select(x => x.Key);
|
||||
foreach (var cid in cid_list)
|
||||
writer.WriteLine($"#. • {cid}");
|
||||
if (cid_list.Count() > 1)
|
||||
dupes.Add(en_str);
|
||||
|
||||
if (cur_en_US.comments.ContainsKey(id))
|
||||
{
|
||||
var en_str = en_US.sections[section.Key].Find(x => x.id == msg.id).str;
|
||||
|
||||
// Handle duplicates
|
||||
if (dupes.Contains(en_str))
|
||||
continue;
|
||||
writer.WriteLine();
|
||||
foreach (var id in msg_to_ids[en_str])
|
||||
{
|
||||
if (id.group == "MSG")
|
||||
writer.WriteLine($"#. • {id.id}");
|
||||
else
|
||||
writer.WriteLine($"#. • {id.group} → {id.id}");
|
||||
}
|
||||
if (msg_to_ids[en_str].Count > 1)
|
||||
dupes.Add(en_str);
|
||||
|
||||
if (lang.comments.ContainsKey(msg.id))
|
||||
{
|
||||
if (is_pot)
|
||||
writer.WriteLine("#.");
|
||||
foreach (var comment in lang.comments[msg.id].Split('\n'))
|
||||
if (comment.Trim() != "")
|
||||
writer.WriteLine((is_pot ? "#. " : "# ") + comment);
|
||||
}
|
||||
if (is_pot)
|
||||
{
|
||||
writer.WriteLine($"msgid {msg.str}");
|
||||
writer.WriteLine("msgstr \"\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine($"msgid {en_str}");
|
||||
writer.WriteLine($"msgstr {msg.str}");
|
||||
}
|
||||
writer.WriteLine("#.");
|
||||
foreach (var comment in cur_en_US.comments[id].Split('\n'))
|
||||
if (comment.Trim() != "")
|
||||
writer.WriteLine("#. " + comment);
|
||||
}
|
||||
if (!is_pot && lang.comments.ContainsKey(id))
|
||||
{
|
||||
foreach (var comment in lang.comments[id].Split('\n'))
|
||||
if (comment.Trim() != "")
|
||||
writer.WriteLine("# " + comment);
|
||||
}
|
||||
// Flag the new/modified messages as requiring work
|
||||
if ((old_en_US != null) && (added_ids.Contains(id) || modified_ids.Contains(id)))
|
||||
writer.WriteLine("#, fuzzy");
|
||||
string msg_str = lang.sections[id.group].Where(x => x.id == id.id).Select(x => x.str).FirstOrDefault();
|
||||
// Special case for MSG_240, which we missed in the last round
|
||||
if (id.group == "MSG" && id.id == "MSG_240" && msg_str == null)
|
||||
writer.WriteLine("#, fuzzy");
|
||||
if (msg_str == null)
|
||||
msg_str = "\"\"";
|
||||
if (is_pot)
|
||||
{
|
||||
writer.WriteLine($"msgid {msg_str}");
|
||||
writer.WriteLine("msgstr \"\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine($"msgid {en_str}");
|
||||
writer.WriteLine($"msgstr {msg_str}");
|
||||
}
|
||||
}
|
||||
}
|
||||
nb_po_saved++;
|
||||
}
|
||||
Console.WriteLine("DONE.");
|
||||
return true;
|
||||
Console.WriteLine("DONE");
|
||||
return nb_po_saved;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -476,9 +554,9 @@ namespace pollock
|
|||
{
|
||||
if (comments != null)
|
||||
{
|
||||
lang.comments.Add(id.id, "");
|
||||
lang.comments.Add(id, "");
|
||||
foreach (var comment in comments)
|
||||
lang.comments[id.id] += comment + "\n";
|
||||
lang.comments[id] += comment + "\n";
|
||||
}
|
||||
// Ignore messages that have the same translation as en-US
|
||||
if (msg_data[0] == msg_data[1])
|
||||
|
@ -528,9 +606,10 @@ namespace pollock
|
|||
writer.WriteLine($"g {section}");
|
||||
foreach (var msg in lang.sections[section])
|
||||
{
|
||||
if (lang.comments.ContainsKey(msg.id))
|
||||
var id = new Id(section, msg.id);
|
||||
if (lang.comments.ContainsKey(id))
|
||||
{
|
||||
foreach (var l in lang.comments[msg.id].Split('\n'))
|
||||
foreach (var l in lang.comments[id].Split('\n'))
|
||||
if (l.Trim() != "")
|
||||
writer.WriteLine($"# {l}");
|
||||
}
|
||||
|
@ -540,16 +619,21 @@ namespace pollock
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new rufus.loc from a list of Language elements.
|
||||
/// Update a rufus.loc section from a language element.
|
||||
/// </summary>
|
||||
/// <param name="path">The path where the new 'rufus.loc' should be created.</param>
|
||||
/// <param name="list">The list of Language elements.</param>
|
||||
/// <param name="lang">The Language elements to update.</param>
|
||||
/// <param name="path">(Optional) The path where 'rufus.loc' is located.</param>
|
||||
/// <returns>true on success, false on error.</returns>
|
||||
static bool UpdateLocFile(string path, Language lang)
|
||||
static bool UpdateLocFile(Language lang, string path = null)
|
||||
{
|
||||
if (lang == null)
|
||||
return false;
|
||||
var target = path + @"\rufus.loc";
|
||||
if (path == null)
|
||||
path = app_path;
|
||||
if (!path.EndsWith("\\"))
|
||||
path += '\\';
|
||||
|
||||
var target = path + "rufus.loc";
|
||||
var lines = File.ReadAllLines(target);
|
||||
using (var writer = new StreamWriter(target, false, encoding))
|
||||
{
|
||||
|
@ -576,21 +660,25 @@ namespace pollock
|
|||
/// <summary>
|
||||
/// Create a new rufus.loc from a list of Language elements.
|
||||
/// </summary>
|
||||
/// <param name="path">The path where the new 'rufus.loc' should be created.</param>
|
||||
/// <param name="list">The list of Language elements.</param>
|
||||
/// <param name="path">(Optional) The path where the new 'rufus.loc' should be created.</param>
|
||||
/// <returns>true on success, false on error.</returns>
|
||||
static bool SaveLocFile(string path, List<Language> list)
|
||||
static bool SaveLocFile(List<Language> list, string path = null)
|
||||
{
|
||||
if ((list == null) || (list.Count == 0))
|
||||
return false;
|
||||
var target = path + @"\rufus.loc";
|
||||
if (path == null)
|
||||
path = app_path;
|
||||
if (!path.EndsWith("\\"))
|
||||
path += '\\';
|
||||
var target = path + "rufus.loc";
|
||||
|
||||
sw.Start();
|
||||
|
||||
Console.WriteLine($"Creating '{target}':");
|
||||
using (var writer = new StreamWriter(target, false, encoding))
|
||||
{
|
||||
var notice = $"### Autogenerated by {app_name} {app_version} for use with Rufus - DO NOT EDIT!!! ###";
|
||||
var notice = $"### Autogenerated by {app_name} {version_str} for use with Rufus - DO NOT EDIT!!! ###";
|
||||
var sep = new String('#', notice.Length);
|
||||
writer.WriteLine(sep);
|
||||
writer.WriteLine(notice);
|
||||
|
@ -620,25 +708,102 @@ namespace pollock
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool DownloadFile(string url, string dest)
|
||||
/// <summary>
|
||||
/// Validate a download URL by checking its HTTP status code.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to validate.</param>
|
||||
/// <returns>true if URL is acessible, false on error.</returns>
|
||||
static bool ValidateDownload(string url)
|
||||
{
|
||||
download_status = 0;
|
||||
in_progress = false;
|
||||
HttpStatusCode status = HttpStatusCode.NotFound;
|
||||
var uri = new Uri(url);
|
||||
WebRequest request = WebRequest.Create(uri);
|
||||
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
||||
request.Method = "HEAD";
|
||||
|
||||
// This is soooooooo retarded. Trying to simply read a 404 response throws a 404 *exception*?!?
|
||||
try
|
||||
{
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
status = response.StatusCode;
|
||||
}
|
||||
catch (WebException we)
|
||||
{
|
||||
HttpWebResponse response = we.Response as HttpWebResponse;
|
||||
status = response.StatusCode;
|
||||
}
|
||||
switch (status)
|
||||
{
|
||||
case HttpStatusCode.OK:
|
||||
return true;
|
||||
default:
|
||||
Console.WriteLine($"Error downloading {url}: {(int)status} - {status}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a file as a string. Codepage is assumed to be UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to download from.</param>
|
||||
/// <returns>The downloaded string or null on error.</returns>
|
||||
static string DownloadString(string url)
|
||||
{
|
||||
string str = null;
|
||||
|
||||
if (!ValidateDownload(url))
|
||||
return null;
|
||||
|
||||
using (wc)
|
||||
{
|
||||
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
|
||||
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
|
||||
|
||||
Console.WriteLine($"Downloading {url}:");
|
||||
sw.Start();
|
||||
|
||||
try
|
||||
{
|
||||
wc.DownloadFileAsync(new Uri(url), dest);
|
||||
str = System.Text.Encoding.UTF8.GetString(wc.DownloadData(new Uri(url)));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("ERROR: " + e.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a file.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to download from.</param>
|
||||
/// <param name="dest">(Optional) The destination file.
|
||||
/// If not provided the file is saved in the current directory, using the last part of the URL as its name.</param>
|
||||
/// <returns>true if the download was complete, false otherwise.</returns>
|
||||
static bool DownloadFile(string url, string dest = null)
|
||||
{
|
||||
download_status = 0;
|
||||
in_progress = false;
|
||||
var uri = new Uri(url);
|
||||
|
||||
if (dest == null)
|
||||
dest = url.Split('/').Last();
|
||||
|
||||
if (!ValidateDownload(url))
|
||||
return false;
|
||||
|
||||
console_x_pos = Console.CursorLeft;
|
||||
using (wc)
|
||||
{
|
||||
wc.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
||||
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
|
||||
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
|
||||
|
||||
sw.Start();
|
||||
|
||||
try
|
||||
{
|
||||
wc.DownloadFileAsync(uri, dest);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(" Error: " + e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -647,16 +812,13 @@ namespace pollock
|
|||
|
||||
Console.WriteLine();
|
||||
if (download_status == 1)
|
||||
{
|
||||
Console.WriteLine("Download complete");
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine("Download has been canceled.");
|
||||
|
||||
Console.WriteLine($"Download has {((download_status == 2) ? "been cancelled" : "failed")}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The event that will fire whenever the progress of the WebClient is changed
|
||||
// Progress event used by DownloadFile()
|
||||
static void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
if (cancel_requested)
|
||||
|
@ -671,23 +833,70 @@ namespace pollock
|
|||
in_progress = true;
|
||||
|
||||
speed = (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds);
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
Console.Write($" {e.ProgressPercentage.ToString("000.0")} % ({speed.ToString("0.00")} KB/s)");
|
||||
Console.SetCursorPosition(console_x_pos, Console.CursorTop);
|
||||
Console.Write($"{e.ProgressPercentage.ToString("0.0"), 5}% ({speed.ToString("0.00")} KB/s)");
|
||||
in_progress = false;
|
||||
}
|
||||
|
||||
// The event that will trigger when the WebClient is completed
|
||||
// Completed event used by DownloadFile()
|
||||
static void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
if (!e.Cancelled)
|
||||
{
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
Console.Write($" 100.0 % ({speed.ToString("0.00")} KB/s)");
|
||||
}
|
||||
Console.SetCursorPosition(console_x_pos, Console.CursorTop);
|
||||
sw.Reset();
|
||||
download_status = (e.Cancelled) ? 2 : 1;
|
||||
if (e.Error != null)
|
||||
{
|
||||
Console.Write("Error: " + e.Error.Message);
|
||||
download_status = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write($"{100.0d.ToString("0.0"),5}% ({speed.ToString("0.00")} KB/s) {(e.Cancelled ? "CANCELLED" : "DONE")}");
|
||||
download_status = (e.Cancelled) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prompt a user for a Y/N question.
|
||||
/// </summary>
|
||||
/// <param name="question">The question string.</param>
|
||||
/// <returns>true if the user answered 'Y'.</returns>
|
||||
static bool PromptForQuestion(string question)
|
||||
{
|
||||
ConsoleKey response;
|
||||
do
|
||||
{
|
||||
Console.Write(question + " [y/n] ");
|
||||
console_x_pos = Console.CursorLeft - 6;
|
||||
response = Console.ReadKey(false).Key;
|
||||
if (response != ConsoleKey.Enter)
|
||||
Console.WriteLine();
|
||||
} while (response != ConsoleKey.Y && response != ConsoleKey.N);
|
||||
// Flush
|
||||
while (Console.KeyAvailable)
|
||||
Console.ReadKey(true);
|
||||
return (response == ConsoleKey.Y);
|
||||
}
|
||||
|
||||
// Event handler for FileSystemWatcher. As usual, this is a completely BACKWARDS
|
||||
// implementation by Microsoft that has to be worked areoun with timers and stuff...
|
||||
private static void OnChanged(object source, FileSystemEventArgs e)
|
||||
{
|
||||
if (in_on_change)
|
||||
return;
|
||||
in_on_change = true;
|
||||
DateTime file_changed_time = File.GetLastWriteTime(e.FullPath);
|
||||
if (file_changed_time >= last_changed.AddMilliseconds(250))
|
||||
{
|
||||
last_changed = file_changed_time;
|
||||
Console.WriteLine("File " + e.FullPath + " was edited at " + file_changed_time.ToLongTimeString());
|
||||
UpdateLocFile(ParsePoFile(e.FullPath));
|
||||
}
|
||||
in_on_change = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Main entrypoint.
|
||||
//
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||
|
@ -696,21 +905,92 @@ namespace pollock
|
|||
cancel_requested = true;
|
||||
};
|
||||
|
||||
Console.WriteLine($"{app_name} {app_version} - Poedit to rufus.loc conversion utility");
|
||||
Console.WriteLine($"{app_name} {version_str} - Poedit to rufus.loc conversion utility");
|
||||
Console.WriteLine();
|
||||
|
||||
var path = @"C:\pollock";
|
||||
var loc = path + @"\download.loc";
|
||||
string loc_url = "https://github.com/pbatard/rufus/raw/master/res/localization/rufus.loc";
|
||||
string ver_url = "https://rufus.ie/Loc.ver";
|
||||
string rufus_url = null;
|
||||
string rufus_file = null;
|
||||
string download_url = null;
|
||||
string po_file = null;
|
||||
int[] update_version = new int[2];
|
||||
|
||||
// Download the loc file
|
||||
//var url = "https://github.com/pbatard/rufus/raw/master/res/localization/rufus.loc";
|
||||
//if (!DownloadFile(url, loc))
|
||||
// goto Exit;
|
||||
// Check for updates of this application
|
||||
var ver = DownloadString(ver_url);
|
||||
if (ver == null)
|
||||
{
|
||||
Console.WriteLine("ERROR: Could not access latest application data.");
|
||||
goto Exit;
|
||||
}
|
||||
foreach (var line in ver.Split('\n'))
|
||||
{
|
||||
var parts = line.Split('=');
|
||||
if (parts.Count() < 2)
|
||||
continue;
|
||||
switch(parts[0].Trim())
|
||||
{
|
||||
case "version":
|
||||
Int32.TryParse(parts[1].Split('.')[0], out update_version[0]);
|
||||
Int32.TryParse(parts[1].Split('.')[1], out update_version[1]);
|
||||
break;
|
||||
case "download_url":
|
||||
download_url = parts[1].Trim();
|
||||
break;
|
||||
case "rufus_url":
|
||||
rufus_url = parts[1].Trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Download new version
|
||||
if ((update_version[0] > version[0]) || ((update_version[0] == version[0]) && (update_version[1] > version[1])))
|
||||
{
|
||||
Console.WriteLine();
|
||||
if (PromptForQuestion("A new version of this application is available! Do you want to download it?"))
|
||||
{
|
||||
if (DownloadFile(download_url))
|
||||
{
|
||||
Console.WriteLine("Now re-launch this program using the latest version.");
|
||||
goto Exit;
|
||||
}
|
||||
Console.WriteLine("Download failed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (rufus_url != null)
|
||||
{
|
||||
// Download the latest version of Rufus to use for translations
|
||||
rufus_file = rufus_url.Split('/').Last();
|
||||
Console.Write($"Checking for the presence of '{rufus_file}'... ");
|
||||
if (File.Exists(rufus_file))
|
||||
{
|
||||
Console.WriteLine("FOUND");
|
||||
}
|
||||
else
|
||||
{
|
||||
var rufus_name = rufus_url.Split('/').Last();
|
||||
Console.WriteLine("MISSING");
|
||||
Console.WriteLine($"{rufus_name} doesn't exist in your translation directory.");
|
||||
Console.WriteLine("This is the required version to validate your changes.");
|
||||
if (PromptForQuestion($"Do you want to download {rufus_name}?")) {
|
||||
Console.SetCursorPosition(console_x_pos, Console.CursorTop - 1);
|
||||
DownloadFile(rufus_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Download the latest loc file
|
||||
Console.Write("Downloading the latest loc file... ");
|
||||
if (!DownloadFile(loc_url))
|
||||
goto Exit;
|
||||
|
||||
var loc_file = loc_url.Split('/').Last();
|
||||
// Convert to CRLF and get all the language ids
|
||||
var lines = File.ReadAllLines(loc);
|
||||
var lines = File.ReadAllLines(loc_file);
|
||||
string id = "", name = "";
|
||||
var list = new List<string[]>();
|
||||
using (var writer = new StreamWriter(loc, false, encoding))
|
||||
using (var writer = new StreamWriter(loc_file, false, encoding))
|
||||
{
|
||||
foreach (var line in lines)
|
||||
{
|
||||
|
@ -722,8 +1002,7 @@ namespace pollock
|
|||
}
|
||||
else if (line.StartsWith("v "))
|
||||
{
|
||||
if (id != "en-US")
|
||||
list.Add(new string[] { name, id, line.Substring(2) });
|
||||
list.Add(new string[] { name, id, line.Substring(2) });
|
||||
}
|
||||
writer.WriteLine(line);
|
||||
}
|
||||
|
@ -733,21 +1012,21 @@ Menu:
|
|||
Console.WriteLine();
|
||||
Console.WriteLine("Please enter the number of the language you want to edit or 'q' to quit:");
|
||||
Console.WriteLine();
|
||||
int split = (list.Count + 1) / 2;
|
||||
for (int i = 0; i < split; i++)
|
||||
int split = list.Count / 2;
|
||||
for (int i = 1; i < split + 1; i++)
|
||||
{
|
||||
name = $"{list[i][0]} ({list[i][1]})";
|
||||
Console.Write($"[{(i+1).ToString("00")}] {name,-29} (v{list[i][2]})");
|
||||
Console.Write($"[{i.ToString("00")}] {name,-29} {$"(v{list[i][2]})",-7}");
|
||||
name = $"{list[i + split][0]} ({list[i + split][1]})";
|
||||
Console.WriteLine($" | [{(i + 1 + split).ToString("00")}] {name,-29} (v{list[i + split][2]})");
|
||||
Console.WriteLine($" | [{(i + split).ToString("00")}] {name,-29} {$"(v{list[i + split][2]})",-7}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
Retry:
|
||||
string input = Console.ReadLine();
|
||||
if (input.StartsWith("q"))
|
||||
if ((input == null) || (input.StartsWith("q")))
|
||||
goto Exit;
|
||||
if (!Int32.TryParse(input, out int number) || (number <= 0) || (number > list.Count))
|
||||
if (!Int32.TryParse(input, out int index) || (index <= 0) || (index > list.Count))
|
||||
{
|
||||
if (input.StartsWith("m"))
|
||||
goto Menu;
|
||||
|
@ -755,28 +1034,98 @@ Retry:
|
|||
goto Retry;
|
||||
}
|
||||
|
||||
number--;
|
||||
Console.WriteLine($"{list[number][0]} was selected");
|
||||
CreatePoFiles(path, ParseLocFile(path, list[number][1]));
|
||||
Console.SetCursorPosition(0, Console.CursorTop - 1);
|
||||
Console.WriteLine($"{list[index][0]} was selected.");
|
||||
Console.WriteLine();
|
||||
po_file = $"{list[index][1]}.po";
|
||||
|
||||
// NB: Can find PoEdit from Computer\HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
|
||||
Language old_en_US = null;
|
||||
if (list[index][2] == list[0][2])
|
||||
{
|
||||
Console.WriteLine("Note: This language is already at the most recent version!");
|
||||
if (!PromptForQuestion("Do you still want to edit it?"))
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
var old_loc_file = $"rufus-{list[index][2]}.loc";
|
||||
Console.WriteLine($"Note: This language is at v{list[index][2]} but the English base it at v{list[0][2]}.");
|
||||
Console.Write($"Checking for the presence of '{old_loc_file}' to compute the differences... ");
|
||||
if (File.Exists(old_loc_file))
|
||||
{
|
||||
Console.WriteLine("FOUND");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("MISSING");
|
||||
Console.Write($"Downloading '{old_loc_file}'... ");
|
||||
var url = "https://github.com/pbatard/rufus/releases/tag/v" + list[index][2];
|
||||
var str = DownloadString(url);
|
||||
if (str == null)
|
||||
goto Exit;
|
||||
var sha = str.Substring(str.IndexOf("/pbatard/rufus/commit/") + 22, 40);
|
||||
url = "https://github.com/pbatard/rufus/raw/" + sha + "/res/localization/rufus.loc";
|
||||
if (!DownloadFile(url, old_loc_file))
|
||||
goto Exit;
|
||||
}
|
||||
var old_langs = ParseLocFile(old_loc_file, "en-US");
|
||||
if ((old_langs == null) || (old_langs.Count != 1))
|
||||
{
|
||||
Console.WriteLine("Error: Unable to get en-US data from previous loc file.");
|
||||
goto Exit;
|
||||
}
|
||||
old_en_US = old_langs[0];
|
||||
}
|
||||
|
||||
//CreatePoFiles(path, ParseLocFile(@"C:\rufus\res\localization"));
|
||||
if (CreatePoFiles(ParseLocFile(loc_file, list[index][1]), old_en_US) != 1)
|
||||
{
|
||||
Console.WriteLine("Failed to create PO file");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//var en_US = ParsePoFile(path + @"\rufus.pot");
|
||||
//var fr_FR = ParsePoFile(path + @"\fr-FR.po");
|
||||
//var ar_SA = ParsePoFile(path + @"\ar-SA.po");
|
||||
//var vi_VN = ParsePoFile(path + @"\vi-VN.po");
|
||||
//List<Language> list = new List<Language>();
|
||||
//list.Add(en_US);
|
||||
//list.Add(ar_SA);
|
||||
//list.Add(fr_FR);
|
||||
//list.Add(vi_VN);
|
||||
//SaveLocFile(path, list);
|
||||
// UpdateLocFile(path + @"\test", fr_FR);
|
||||
// Watch for file modifications
|
||||
FileSystemWatcher watcher = new FileSystemWatcher();
|
||||
watcher.Path = app_path;
|
||||
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
|
||||
watcher.Filter = po_file;
|
||||
watcher.Changed += new FileSystemEventHandler(OnChanged);
|
||||
watcher.EnableRaisingEvents = true;
|
||||
|
||||
// Open the file in PoEdit if we can
|
||||
var poedit = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + @"\Poedit\Poedit.exe";
|
||||
if (File.Exists(poedit))
|
||||
{
|
||||
Console.WriteLine();
|
||||
// Console.WriteLine("Please press any key to launch Poedit and edit the PO file.");
|
||||
Console.WriteLine("*************************************************************************************");
|
||||
Console.WriteLine($"* The {list[index][0]} translation file is now ready to be edited in Poedit.");
|
||||
Console.WriteLine("* Please look for any entries highlited in red: They are the ones requiring an update.");
|
||||
Console.WriteLine("*");
|
||||
Console.WriteLine("* Whenever you save your changes in Poedit, 'rufus.loc' will be updated for testing");
|
||||
Console.WriteLine($"* with '{rufus_file}'. >>>PLEASE MAKE SURE YOU DON'T CLOSE THIS PROGRAM!<<<");
|
||||
Console.WriteLine("* When you are done editing your translation, simply close Poedit.");
|
||||
Console.WriteLine("*************************************************************************************");
|
||||
WaitForKey("Press any key to launch Poedit...");
|
||||
|
||||
Process ExternalProcess = new Process();
|
||||
ExternalProcess.StartInfo.FileName = poedit;
|
||||
ExternalProcess.StartInfo.WorkingDirectory = app_path;
|
||||
ExternalProcess.StartInfo.Arguments = $"{list[index][1]}.po";
|
||||
ExternalProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
|
||||
ExternalProcess.Start();
|
||||
Console.SetCursorPosition(0, Console.CursorTop - 1);
|
||||
Console.WriteLine("Running Poedit... ");
|
||||
ExternalProcess.WaitForExit();
|
||||
Console.WriteLine("Poedit was closed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Poedit was not found. You will have to launch it and open the");
|
||||
Console.WriteLine($"'{app_path + list[index][1]}.po' file manually.");
|
||||
}
|
||||
|
||||
Exit:
|
||||
WaitForKey();
|
||||
WaitForKey("Press any key to exit...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
# http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-LCID%5D.pdf
|
||||
# for the LCID (0x####) codes you should use
|
||||
l "en-US" "English (English)" 0x0409, 0x0809, 0x0c09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x3809, 0x3c09, 0x4009, 0x4409, 0x4809
|
||||
v 1.0.23
|
||||
v 3.2
|
||||
|
||||
g IDD_DIALOG
|
||||
t IDS_DRIVE_PROPERTIES_TXT "Drive Properties"
|
||||
|
@ -571,7 +571,7 @@ t MSG_306 "Fast-zeroing drive: %0.1f%% completed"
|
|||
|
||||
l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001
|
||||
a "r"
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -982,7 +982,7 @@ t MSG_305 "إستخدام هذا الخيار لبيان م إذا كنت تري
|
|||
|
||||
################################################################################
|
||||
l "az-AZ" "Azerbaijani (Azərbaycanca)" 0x042c, 0x782c
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -1393,7 +1393,7 @@ t MSG_305 "Windows'u başqa bir diskə yükləmək üçün bu cihazı istifadə
|
|||
|
||||
######################################################################
|
||||
l "bg-BG" "Bulgarian (Български)" 0x0402
|
||||
v 1.0.22
|
||||
v 2.16
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -1784,7 +1784,7 @@ t MSG_118 "Windows To Go (Windows за USB Flash устройство)"
|
|||
|
||||
################################################################################
|
||||
l "zh-CN" "Chinese Simplified (简体中文)" 0x0804, 0x1004
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -2179,7 +2179,7 @@ t MSG_305 "请选择您希望将 Windows 安装至其他驱动器,还是直接
|
|||
|
||||
################################################################################
|
||||
l "zh-TW" "Chinese Traditional (正體中文)" 0x0404, 0x0c04, 0x1404, 0x7c04
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -2557,7 +2557,7 @@ t MSG_305 "是否要使用此裝置來安裝 Windows 在另一個磁碟上,"
|
|||
|
||||
################################################################################
|
||||
l "hr-HR" "Croatian (Hrvatski)" 0x041a, 0x081a, 0x101a
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -2965,7 +2965,7 @@ t MSG_305 "Ovom opcijom naznačite ako želite koristiti ovaj uređaj kako bi in
|
|||
|
||||
################################################################################
|
||||
l "cs-CZ" "Czech (Čeština)" 0x0405
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -3375,7 +3375,7 @@ t MSG_305 "Touto volbou označte, zda chcete toto zařízení používat k insta
|
|||
|
||||
################################################################################
|
||||
l "da-DK" "Danish (Dansk)" 0x0406
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -3787,7 +3787,7 @@ t MSG_305 "Brug dette alternativ for at angive om du vil bruge denne enhed til a
|
|||
|
||||
################################################################################
|
||||
l "nl-NL" "Dutch (Nederlands)" 0x0413, 0x0813
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -4190,7 +4190,7 @@ t MSG_305 "Gebruik deze optie om aan te geven of u dit apparaat wilt gebruiken o
|
|||
|
||||
################################################################################
|
||||
l "fi-FI" "Finnish (Suomi)" 0x040B
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -4599,7 +4599,7 @@ t MSG_305 "Käytä tätä vaihtoehtoa valitaksesi haluatko käyttää valittua l
|
|||
|
||||
################################################################################
|
||||
l "fr-FR" "French (Français)" 0x040c, 0x080c, 0x0c0c, 0x100c, 0x140c, 0x180c, 0x1c0c, 0x200c, 0x240c, 0x280c, 0x2c0c, 0x300c, 0x340c, 0x380c, 0xe40c
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -5012,7 +5012,7 @@ t MSG_305 "Utilisez cette option pour indiquer si vous voulez utiliser ce périp
|
|||
|
||||
################################################################################
|
||||
l "de-DE" "German (Deutsch)" 0x0407, 0x0807, 0x0c07, 0x1007, 0x1407
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -5407,7 +5407,7 @@ t MSG_305 "Wollen Sie Windows auf einem anderen Laufwerk installieren oder Windo
|
|||
|
||||
################################################################################
|
||||
l "el-GR" "Greek (Ελληνικά)" 0x0408
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -5823,7 +5823,7 @@ t MSG_305 "Επιλέξτε αυτό αν θέλετε να χρησιμοποι
|
|||
################################################################################
|
||||
l "he-IL" "Hebrew (עברית)" 0x040d
|
||||
a "r"
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -6238,7 +6238,7 @@ t MSG_305 "ניתן להשתמש באפשרות זו כדי לציין האם ב
|
|||
|
||||
################################################################################
|
||||
l "hu-HU" "Hungarian (Magyar)" 0x040e
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -6649,7 +6649,7 @@ t MSG_305 "Ezt a lehetőséget arra használd, hogy jelezd, ezt az eszközt szer
|
|||
|
||||
################################################################################
|
||||
l "id-ID" "Indonesian (Bahasa Indonesia)" 0x0421
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -7062,7 +7062,7 @@ t MSG_305 "Gunakan opsi ini jika Anda ingin menggunakan perangkat ini untuk meng
|
|||
|
||||
################################################################################
|
||||
l "it-IT" "Italian (Italiano)" 0x0410, 0x0810
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -7474,7 +7474,7 @@ t MSG_305 "Usa questa opzione per indicare se vuoi usare questa unità per insta
|
|||
|
||||
######################################################################
|
||||
l "ja-JP" "Japanese (日本語)" 0x0411
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -7902,7 +7902,7 @@ t MSG_305 "このデバイスを使用して別のディスクにWindowsをイ
|
|||
|
||||
################################################################################
|
||||
l "ko-KR" "Korean (한국어)" 0x0412
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -8313,7 +8313,7 @@ t MSG_305 "이 장치를 사용하여 다른 디스크에 Windows를 설치하
|
|||
|
||||
################################################################################
|
||||
l "lv-LV" "Latvian (Latviešu)" 0x0426
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -8721,7 +8721,7 @@ t MSG_305 "Izmantojiet šo opciju, lai norādīt vai vēlaties izmantot ierīci
|
|||
|
||||
################################################################################
|
||||
l "lt-LT" "Lithuanian (Lietuvių)" 0x0427
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -9137,7 +9137,7 @@ t MSG_305 "Šią parinktį naudokite norėdami nurodyti ar naudosite šį įreng
|
|||
|
||||
################################################################################
|
||||
l "ms-MY" "Malay (Bahasa Malaysia)" 0x043e, 0x083e
|
||||
v 1.0.19
|
||||
v 2.5
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -9515,7 +9515,7 @@ t MSG_286 "Mensifarkan pemacu: %0.1f%% selesai"
|
|||
|
||||
################################################################################
|
||||
l "nb-NO" "Norwegian (Norsk)" 0x0414
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -9929,7 +9929,7 @@ t MSG_305 "Bruk dette alternativet for å angi om du vil bruke denne enheten til
|
|||
################################################################################
|
||||
l "fa-IR" "Persian (فارسی)" 0x0429
|
||||
a "r"
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -10358,7 +10358,7 @@ t MSG_305 "با استفاده از این گزینه مشخص کنید که آ
|
|||
|
||||
################################################################################
|
||||
l "pl-PL" "Polish (Polski)" 0x0415
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -10772,7 +10772,7 @@ t MSG_305 "Użyj tej opcji aby wskazać, czy chcesz użyć tego dysku do instala
|
|||
|
||||
################################################################################
|
||||
l "pt-BR" "Portuguese Brazilian (Português do Brasil)" 0x0416
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -11194,7 +11194,7 @@ t MSG_305 "Use esta opção caso queira instalar o Windows neste dispositivo ou
|
|||
|
||||
################################################################################
|
||||
l "pt-PT" "Portuguese Standard (Português)" 0x0816
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -11611,7 +11611,7 @@ t MSG_305 "Usar esta opção se pretende utilizar este dispositivo para instalar
|
|||
|
||||
################################################################################
|
||||
l "ro-RO" "Romanian (Română)" 0x0418, 0x0818
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -12021,7 +12021,7 @@ t MSG_305 "Utilizaţi această opţiune dacă doriţi să utilizaţi acest dispo
|
|||
|
||||
################################################################################
|
||||
l "ru-RU" "Russian (Русский)" 0x0419, 0x0819
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -12426,7 +12426,7 @@ t MSG_305 "Используйте этот параметр, чтобы указ
|
|||
|
||||
################################################################################
|
||||
l "sr-SP" "Serbian (Srpski)" 0x241a, 0x081a, 0x181a, 0x2c1a, 0x701a, 0x7c1a
|
||||
v 1.0.22
|
||||
v 2.16
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -12816,7 +12816,7 @@ t MSG_117 "Standardna instalacija Windows-a"
|
|||
|
||||
################################################################################
|
||||
l "sk-SK" "Slovak (Slovensky)" 0x041B
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -13229,7 +13229,7 @@ t MSG_305 "Použite túto možnosť, ak chcete použiť toto zariadenie na inšt
|
|||
|
||||
################################################################################
|
||||
l "sl-SI" "Slovenian (Slovenščina)" 0x0424
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -13640,7 +13640,7 @@ t MSG_305 "Tu izberete, ali želite uporabiti to napravo, da bi namestili operac
|
|||
|
||||
################################################################################
|
||||
l "es-ES" "Spanish (Español)" 0x040a, 0x080a, 0x0c0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x540a, 0x580a
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -14056,7 +14056,7 @@ t MSG_305 "Use esta opción para indicar si desea usar este dispositivo para ins
|
|||
|
||||
################################################################################
|
||||
l "sv-SE" "Swedish (Svenska)" 0x041d, 0x081d
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -14465,7 +14465,7 @@ t MSG_305 "Använd det här alternativet om du vill använda den här enheten f
|
|||
|
||||
################################################################################
|
||||
l "th-TH" "Thai (ไทย)" 0x041e
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -14876,7 +14876,7 @@ t MSG_305 "เลือกตัวเลือกนี้หากต้อง
|
|||
|
||||
################################################################################
|
||||
l "tr-TR" "Turkish (Türkçe)" 0x041F
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -15292,7 +15292,7 @@ t MSG_305 "Windows'u başka bir diske yüklemek için bu cihazı kullanmak istey
|
|||
|
||||
################################################################################
|
||||
l "uk-UA" "Ukrainian (Українська)" 0x0422
|
||||
v 1.0.23
|
||||
v 3.0
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
@ -15702,7 +15702,7 @@ t MSG_305 "Використовуйте цей параметр, щоб вказ
|
|||
|
||||
################################################################################
|
||||
l "vi-VN" "Vietnamese (Tiếng Việt)" 0x042A
|
||||
v 1.0.22
|
||||
v 2.16
|
||||
b "en-US"
|
||||
|
||||
g IDD_DIALOG
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 3.2.1335"
|
||||
CAPTION "Rufus 3.2.1336"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -392,8 +392,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,2,1335,0
|
||||
PRODUCTVERSION 3,2,1335,0
|
||||
FILEVERSION 3,2,1336,0
|
||||
PRODUCTVERSION 3,2,1336,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -411,13 +411,13 @@ BEGIN
|
|||
VALUE "Comments", "https://akeo.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "3.2.1335"
|
||||
VALUE "FileVersion", "3.2.1336"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
|
||||
VALUE "OriginalFilename", "rufus-3.2.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "3.2.1335"
|
||||
VALUE "ProductVersion", "3.2.1336"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Reference in a new issue