diff --git a/res/localization/ChangeLog.txt b/res/localization/ChangeLog.txt new file mode 100644 index 00000000..a55e4764 --- /dev/null +++ b/res/localization/ChangeLog.txt @@ -0,0 +1,14 @@ +This file lists any change that has been applied to the en-US translation of +rufus.loc since its original version. Translators are expected to keep their +translations up to date by monitoring this file on regular basis and applying +the same changes. + +Remember to also update the version number for your translation ('v x.y.z') +once you have matched all the changes that occurred for the en-US translation. + + +o Version 1.0.1 (2013.10.28) + - MSG_061 "Please insert a media in drive." -> "Please insert a removable media in drive." + - MSG_071 "Unable to create formatting thread." -> "Unable to start thread." +o Version 1.0.0 (2013.10.20) + - Initial version \ No newline at end of file diff --git a/res/localization/new_translation.loc b/res/localization/new_translation.loc index 4edbab47..2e7f5b6b 100644 --- a/res/localization/new_translation.loc +++ b/res/localization/new_translation.loc @@ -48,9 +48,10 @@ ################################################################################ l "zz-ZZ" "LangName_EN (LangName_ZZ)" 0x1234, 0xabcd -# See http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx or +# See http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx or # 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 +v 1.0.1 # Main dialog g IDD_DIALOG @@ -283,8 +284,8 @@ t MSG_151 "Use this if you want to install an OS in EFI mode, but need to access "the USB content from Windows XP" t MSG_152 "The preferred option to install an OS in EFI mode and when " "USB access is not required for Windows XP" -t MSG_153 "Test pattern: 0x%02X" -t MSG_154 "Test pattern: 0x%02X, 0x%02X" +t MSG_153 "Test pattern: 0x%02X" +t MSG_154 "Test pattern: 0x%02X, 0x%02X" t MSG_155 "Test pattern: 0x%02X, 0x%02X, 0x%02X" t MSG_156 "Test pattern: 0x%02X, 0x%02X, 0x%02X, 0x%02X" t MSG_157 "Sets the target filesystem" diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc index b6c9aeab..09215bc9 100644 --- a/res/localization/rufus.loc +++ b/res/localization/rufus.loc @@ -2,6 +2,7 @@ ################################################################################ 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.1 g IDD_MESSAGES t MSG_001 "Other instance detected" t MSG_002 "Another Rufus application is running.\n" @@ -275,6 +276,7 @@ t MSG_259 "Force update" ################################################################################ l "zh-CN" "Chinese Simplified (简体中文)" 0x0404, 0x0804, 0x0c04, 0x1004, 0x1404 +v 1.0.0 b "en-US" g IDD_DIALOG @@ -356,6 +358,7 @@ t MSG_007 "撤消" ################################################################################ l "fr-FR" "French (Français)" 0x040c, 0x080c, 0x0c0c, 0x100c, 0x140c, 0x180c, 0x1c0c, 0x200c, 0x240c, 0x280c, 0x2c0c, 0x300c, 0x340c, 0x380c, 0xe40c +v 1.0.1 b "en-US" g IDD_DIALOG @@ -695,6 +698,7 @@ t MSG_259 "Forçage de mise à jour" ################################################################################ l "hu-HU" "Hungarian (Magyar)" 0x040e +v 1.0.0 b "en-US" g IDD_DIALOG @@ -1008,6 +1012,7 @@ t MSG_259 "'ErÅ‘szakos' frissítés" ################################################################################ l "it-IT" "Italian (Italiano)" 0x0410, 0x0810 +v 1.0.0 b "en-US" g IDD_DIALOG diff --git a/src/localization.c b/src/localization.c index fc4d7c54..1f53993a 100644 --- a/src/localization.c +++ b/src/localization.c @@ -49,7 +49,7 @@ const loc_parse parse_cmd[9] = { // Base translation to add on top of (eg. "English (UK)" can be used to build on top of "English (US)" { 'b', LC_BASE, "s" }, // b "en_US" // Version to use for the localization commandset and API - { 'v', LC_VERSION, "ii" }, // v 1.0 // TODO: NOT IMPLEMENTED YET + { 'v', LC_VERSION, "u" }, // v 1.0.2 // Translate the text control associated with an ID { 't', LC_TEXT, "cs" }, // t IDC_CONTROL "Translation" // Set the section/dialog to which the next commands should apply @@ -331,9 +331,6 @@ void _exit_localization(BOOL reinit) { /* * Validate and store localization command data - * - * TODO: Do we need to store a revert for every action we execute here, - * or do we want to reinstantiate the dialogs? */ BOOL dispatch_loc_cmd(loc_cmd* lcmd) { @@ -373,10 +370,6 @@ BOOL dispatch_loc_cmd(loc_cmd* lcmd) dlg_index = lcmd->ctrl_id - IDD_DIALOG; free_loc_cmd(lcmd); break; - case LC_VERSION: - luprintf("GOT VERSION: %d.%d\n", lcmd->num[0], lcmd->num[1]); - free_loc_cmd(lcmd); - break; case LC_BASE: base_locale = get_locale_from_name(lcmd->txt[0], FALSE); if (base_locale != NULL) { @@ -401,7 +394,6 @@ err: /* * Apply stored localization commands to a specific dialog * If hDlg is NULL, apply the commands against an active Window - * TODO: if dlg_id is <0, apply all */ void apply_localization(int dlg_id, HWND hDlg) { diff --git a/src/localization.h b/src/localization.h index ceff2336..7a07eb8d 100644 --- a/src/localization.h +++ b/src/localization.h @@ -23,9 +23,13 @@ #pragma once // Number of concurrent localization messages. Must be a power of 2. -#define LOC_MESSAGE_NB 8 -#define LOC_MESSAGE_SIZE 2048 -#define LOC_HTAB_SIZE 512 +#define LOC_MESSAGE_NB 8 +#define LOC_MESSAGE_SIZE 2048 +#define LOC_HTAB_SIZE 512 + +// The [v]ersion major from a translation must match this number or +// the translation will be ignored +#define LOC_FRAMEWORK_VERSION 1 #define luprint(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr) #define luprintf(msg, ...) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr, __VA_ARGS__) diff --git a/src/parser.c b/src/parser.c index 2702f1c7..592ce839 100644 --- a/src/parser.c +++ b/src/parser.c @@ -122,18 +122,18 @@ static loc_cmd* get_loc_cmd(char c, char* line) { goto err; } break; - case 'u': // comma separated list of unsigned integers (to end of line) + case 'u': // comma or dot separated list of unsigned integers (to end of line) // count the number of commas lcmd->unum_size = 1; for (l=i; line[l] != 0; l++) { - if (line[l] == ',') + if ((line[l] == '.') || (line[l] == ',')) lcmd->unum_size++; } lcmd->unum = (uint32_t*)malloc(lcmd->unum_size * sizeof(uint32_t)); - token = strtok(&line[i], ","); + token = strtok(&line[i], ".,"); for (l=0; (lunum_size) && (token != NULL); l++) { lcmd->unum[l] = (int32_t)strtol(token, &endptr, 0); - token = strtok(NULL, ","); + token = strtok(NULL, ".,"); } if ((token != NULL) || (l != lcmd->unum_size)) { luprint("internal error (unexpected number of numeric values)"); @@ -234,6 +234,8 @@ BOOL get_supported_locales(const char* filename) size_t i; loc_cmd *lcmd = NULL, *last_lcmd = NULL; long end_of_block; + int version_line_nr = 0; + uint32_t loc_base_minor = -1, loc_base_micro = -1; fd = open_loc_file(filename); if (fd == NULL) @@ -250,29 +252,78 @@ BOOL get_supported_locales(const char* filename) loc_line_nr++; // Skip leading spaces i = strspn(line, space); - if (line[i] != 'l') + if ((line[i] != 'l') && (line[i] != 'v')) continue; // line[i] is not NUL so i+1 is safe to access lcmd = get_loc_cmd(line[i], &line[i+1]); - if ((lcmd == NULL) || (lcmd->command != LC_LOCALE)) { + if ((lcmd == NULL) || ((lcmd->command != LC_LOCALE) && (lcmd->command != LC_VERSION))) { free_loc_cmd(lcmd); continue; } - // we use num[0] and num[1] as block delimiter index for this locale in the file - if (last_lcmd != NULL) { - last_lcmd->num[1] = (int32_t)end_of_block; + switch (lcmd->command) { + case LC_LOCALE: + // we use num[0] and num[1] as block delimiter index for this locale in the file + if (last_lcmd != NULL) { + if (version_line_nr == 0) { + uprintf("localization: no compatible version was found - this locale will be ignored\n"); + list_del(&last_lcmd->list); + free_loc_cmd(last_lcmd); + } else { + last_lcmd->num[1] = (int32_t)end_of_block; + } + } + lcmd->num[0] = (int32_t)ftell(fd); + // Add our locale command to the locale list + list_add_tail(&lcmd->list, &locale_list); + uprintf("localization: found locale '%s'\n", lcmd->txt[0]); + last_lcmd = lcmd; + version_line_nr = 0; + break; + case LC_VERSION: + if (version_line_nr != 0) { + luprintf("[v]ersion was already provided at line %d", version_line_nr); + } else if (lcmd->unum_size != 3) { + luprint("[v]ersion format is invalid"); + } else if (last_lcmd == NULL) { + luprint("[v]ersion cannot precede [l]ocale"); + } else if (lcmd->unum[0] != LOC_FRAMEWORK_VERSION) { + // If the localization framework evolved in a manner that makes existing + // translations incompatible, we need to discard them. + luprint("[v]ersion is not compatible with this framework"); + } else if (loc_base_minor == -1) { + // We use the first version from our loc file (usually en-US) as our base + // as it should always be the most up to date. + loc_base_minor = lcmd->unum[1]; + loc_base_micro = lcmd->unum[0]; + version_line_nr = loc_line_nr; + } else if (lcmd->unum[1] < loc_base_minor) { + luprintf("the version of this locale is incompatible with this version of " APPLICATION_NAME " and MUST be updated to at least v%d.%d.0", + LOC_FRAMEWORK_VERSION, loc_base_minor); + } else { + if (lcmd->unum[2] < loc_base_micro) { + luprintf("the version of this translation is older than the base one and may result in some messages not being properly translated.\n" + "If you are the translator, please update your translation with the changes that intervened between v%d.%d.%d and v%d.%d.%d.\n" + "See https://github.com/pbatard/rufus/blob/master/res/localization/ChangeLog.txt", + LOC_FRAMEWORK_VERSION, loc_base_minor, lcmd->unum[2], LOC_FRAMEWORK_VERSION, loc_base_minor, loc_base_micro); + } + version_line_nr = loc_line_nr; + } + free_loc_cmd(lcmd); + break; } - lcmd->num[0] = (int32_t)ftell(fd); - // Add our locale command to the locale list - list_add_tail(&lcmd->list, &locale_list); - uprintf("localization: found locale '%s'\n", lcmd->txt[0]); - last_lcmd = lcmd; } while (1); - if (last_lcmd != NULL) - last_lcmd->num[1] = (int32_t)ftell(fd); + if (last_lcmd != NULL) { + if (version_line_nr == 0) { + uprintf("localization: no compatible version was found - this locale will be ignored\n"); + list_del(&last_lcmd->list); + free_loc_cmd(last_lcmd); + } else { + last_lcmd->num[1] = (int32_t)ftell(fd); + } + } r = !list_empty(&locale_list); if (r == FALSE) - uprintf("localization: '%s' contains no locale sections\n", filename); + uprintf("localization: '%s' contains no valid locale sections\n", filename); out: if (fd != NULL) diff --git a/src/rufus.c b/src/rufus.c index b259fd14..b3bef654 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -2033,7 +2033,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if ( (!get_supported_locales(loc_file)) || ((selected_locale = ((locale_name == NULL)?get_locale_from_lcid(lcid, TRUE):get_locale_from_name(locale_name, TRUE))) == NULL) ) { uprintf("FATAL: Could not access locale!\n"); - MessageBoxU(NULL, "The locale data is missing. This application will now exit.", + MessageBoxU(NULL, "The locale data is missing or invalid. This application will now exit." + // TODO: remove this line for release! + "\n\nTRANSLATORS: You need to add a 'v 1.0.0' line to your loc file. See the latest 'new_translation.loc'", "Fatal error", MB_ICONSTOP); goto out; } diff --git a/src/rufus.rc b/src/rufus.rc index af6cee5f..23831a57 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.4.0.299" +CAPTION "Rufus v1.4.0.300" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,291,50,14 @@ -285,8 +285,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,299 - PRODUCTVERSION 1,4,0,299 + FILEVERSION 1,4,0,300 + PRODUCTVERSION 1,4,0,300 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -303,13 +303,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.4.0.299" + VALUE "FileVersion", "1.4.0.300" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.4.0.299" + VALUE "ProductVersion", "1.4.0.300" END END BLOCK "VarFileInfo"