diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-09 17:27:33 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-09 17:27:33 +0000 |
commit | afebae164ec8e050af2b1952be53b5fecd3400f7 (patch) | |
tree | b2e3dafa68acfb23e54709ea964090c6498558a6 | |
parent | bc68e0d907e34d22f63c0bc6ab76ea934eb7c545 (diff) | |
download | chromium_src-afebae164ec8e050af2b1952be53b5fecd3400f7.zip chromium_src-afebae164ec8e050af2b1952be53b5fecd3400f7.tar.gz chromium_src-afebae164ec8e050af2b1952be53b5fecd3400f7.tar.bz2 |
Localized Chromoting Host on Windows.
This CL introduces remoting/tools/localize.py script. The script is based on Jinja2 templating language. It is used to generate localizable resources (string table, dialogs, message table and version information) from a common template. The translated strings are taken from json files (used by the webapp as well), which, in turn, are generated from remoting_strings.grd.
Collateral changes:
- Branding of Window resources has been moved to remoting_strings.grd. .ver files are not used anymore.
- Updated verify_resources.py so that it could recognize strings used by Jinja2 templates.
- Fixed the dialog layouts for RTL languages.
TBR=cpu@chromium.org
BUG=155204
Review URL: https://chromiumcodereview.appspot.com/18323017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210591 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | remoting/branding_Chrome | 8 | ||||
-rw-r--r-- | remoting/branding_Chromium | 8 | ||||
-rw-r--r-- | remoting/host/plugin/remoting_host_plugin.ver | 5 | ||||
-rw-r--r-- | remoting/host/remoting_host_messages.mc | 61 | ||||
-rw-r--r-- | remoting/host/win/core.rc | 87 | ||||
-rw-r--r-- | remoting/host/win/core.rc.jinja2 | 67 | ||||
-rw-r--r-- | remoting/host/win/core_resource.h | 16 | ||||
-rw-r--r-- | remoting/host/win/host_messages.mc.jinja2 | 89 | ||||
-rw-r--r-- | remoting/host/win/remoting_core.ver | 4 | ||||
-rw-r--r-- | remoting/host/win/remoting_desktop.ver | 4 | ||||
-rw-r--r-- | remoting/host/win/remoting_host.ver | 4 | ||||
-rw-r--r-- | remoting/host/win/version.rc.jinja2 | 72 | ||||
-rw-r--r-- | remoting/remoting.gyp | 215 | ||||
-rw-r--r-- | remoting/resources/remoting_strings.grd | 69 | ||||
-rw-r--r-- | remoting/tools/DEPS | 1 | ||||
-rwxr-xr-x | remoting/tools/localize.py | 718 | ||||
-rwxr-xr-x | remoting/tools/verify_resources.py | 6 | ||||
-rw-r--r-- | remoting/version.rc.version | 65 |
18 files changed, 1201 insertions, 298 deletions
diff --git a/remoting/branding_Chrome b/remoting/branding_Chrome index 1307495..49e1e88 100644 --- a/remoting/branding_Chrome +++ b/remoting/branding_Chrome @@ -1,13 +1,7 @@ -COMPANY_FULLNAME=Google Inc. -PRODUCT_FULLNAME=Chrome Remote Desktop -COPYRIGHT=Copyright (c) 2012 Google Inc. All Rights Reserved. +COPYRIGHT=Copyright 2013 Google Inc. All Rights Reserved. HOST_PLUGIN_FILE_NAME=Chrome Remote Desktop Host HOST_PLUGIN_DESCRIPTION=Allow another user to access your computer securely over the Internet. -HOST_ME2ME_FILE_NAME=Chrome Remote Desktop Host -HOST_ME2ME_DESCRIPTION=Chrome Remote Desktop Host DAEMON_FILE_NAME=Chrome Remote Desktop Host Service -DESKTOP_DESCRIPTION=Chrome Remote Desktop Integration Process -CORE_DESCRIPTION=Chrome Remote Desktop Core MAC_BUNDLE_ID=com.google.Chrome MAC_CREATOR=rimZ MAC_HOST_BUNDLE_ID=com.google.chrome_remote_desktop.remoting_me2me_host diff --git a/remoting/branding_Chromium b/remoting/branding_Chromium index 5d3d740..22f3621 100644 --- a/remoting/branding_Chromium +++ b/remoting/branding_Chromium @@ -1,13 +1,7 @@ -COMPANY_FULLNAME=The Chromium Authors -PRODUCT_FULLNAME=Chromoting -COPYRIGHT=Copyright (c) 2012 The Chromium Authors. All Rights Reserved. +COPYRIGHT=Copyright 2013 The Chromium Authors. All Rights Reserved. HOST_PLUGIN_FILE_NAME=Chromoting Host HOST_PLUGIN_DESCRIPTION=Allow another user to access your computer securely over the Internet. -HOST_ME2ME_FILE_NAME=Chromoting Host -HOST_ME2ME_DESCRIPTION=Chromoting Host DAEMON_FILE_NAME=Chromoting Host Service -DESKTOP_DESCRIPTION=Chromoting Integration Process -CORE_DESCRIPTION=Chromoting Core MAC_BUNDLE_ID=org.chromium.Chromium MAC_CREATOR=Cr24 MAC_HOST_BUNDLE_ID=org.chromium.chromoting.remoting_me2me_host diff --git a/remoting/host/plugin/remoting_host_plugin.ver b/remoting/host/plugin/remoting_host_plugin.ver deleted file mode 100644 index 0416488..0000000 --- a/remoting/host/plugin/remoting_host_plugin.ver +++ /dev/null @@ -1,5 +0,0 @@ -BINARY=BINARY_HOST_PLUGIN -FILE_TYPE=VFT_DLL -HOST_PLUGIN_MIME_TYPE=application/vnd.chromium.remoting-host -INTERNAL_NAME=remoting_host_plugin.dll -ORIGINAL_FILENAME=remoting_host_plugin.dll diff --git a/remoting/host/remoting_host_messages.mc b/remoting/host/remoting_host_messages.mc deleted file mode 100644 index 0b5c677..0000000 --- a/remoting/host/remoting_host_messages.mc +++ /dev/null @@ -1,61 +0,0 @@ -SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS - Informational=0x1:STATUS_SEVERITY_INFORMATIONAL - Warning=0x2:STATUS_SEVERITY_WARNING - Error=0x3:STATUS_SEVERITY_ERROR) - -FacilityNames=(Host=0x0:FACILITY_HOST) - -LanguageNames=(English=0x409:MSG00409) - -; // The categories of events. -MessageIdTypedef=WORD - -MessageId=0x1 -SymbolicName=HOST_CATEGORY -Language=English -Host -. - - -; // The message definitions. -MessageIdTypedef=DWORD - -MessageId=1 -Severity=Informational -Facility=Host -SymbolicName=MSG_HOST_CLIENT_CONNECTED -Language=English -Client connected: %1. -. - -MessageId=2 -Severity=Informational -Facility=Host -SymbolicName=MSG_HOST_CLIENT_DISCONNECTED -Language=English -Client disconnected: %1. -. - -MessageId=3 -Severity=Error -Facility=Host -SymbolicName=MSG_HOST_CLIENT_ACCESS_DENIED -Language=English -Access denied for client: %1. -. - -MessageId=4 -Severity=Informational -Facility=Host -SymbolicName=MSG_HOST_CLIENT_ROUTING_CHANGED -Language=English -Channel IP for client: %1 ip='%2' host_ip='%3' channel='%4' connection='%5'. -. - -MessageId=5 -Severity=Informational -Facility=Host -SymbolicName=MSG_HOST_STARTED -Language=English -Host started for user: %1. -. diff --git a/remoting/host/win/core.rc b/remoting/host/win/core.rc deleted file mode 100644 index 1bec0ba..0000000 --- a/remoting/host/win/core.rc +++ /dev/null @@ -1,87 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "core_resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN -#ifdef OFFICIAL_BUILD - IDS_DISPLAY_SERVICE_NAME "Chrome Remote Desktop Service" - IDS_SERVICE_DESCRIPTION "This service enables incoming connections from Chrome Remote Desktop clients." - IDS_CONTROLLER "Chrome Remote Desktop Host Controller" -#else - IDS_DISPLAY_SERVICE_NAME "Chromoting Service" - IDS_SERVICE_DESCRIPTION "This service enables incoming connections from Chromoting clients." - IDS_CONTROLLER "Chromoting Host Controller" -#endif -END - -IDD_VERIFY_CONFIG_DIALOG ICON "remoting/resources/chromoting.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_VERIFY_CONFIG_DIALOG DIALOGEX 0, 0, 221, 106 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUPWINDOW | WS_CAPTION -EXSTYLE 0 -CAPTION "kTitle" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - LTEXT "kConfirmConfigChange",IDC_MESSAGE,7,7,207,30 - LTEXT "kAccount",IDC_EMAIL_LABEL,7,38,50,30 - LTEXT "kEmail",IDC_EMAIL,60,38,110,30 - LTEXT "kPin",IDC_PIN_LABEL,7,55,50,30 - EDITTEXT IDC_PIN,60,55,100,15,WS_TABSTOP | ES_PASSWORD | ES_NUMBER - DEFPUSHBUTTON "kOK",IDOK,68,86,68,14,WS_TABSTOP - PUSHBUTTON "kCancel",IDCANCEL,146,86,68,14,WS_TABSTOP -END - -IDD_DISCONNECT DIALOGEX 0, 0, 145, 24 -STYLE DS_SETFONT | WS_POPUP -EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW -FONT 9, "Microsoft Sans Serif", 400, 0, 0x0 -BEGIN - DEFPUSHBUTTON "kDisconnectButton",IDC_DISCONNECT,68,5,70,14 - LTEXT "kSharingWith",IDC_DISCONNECT_SHARINGWITH,18,7,43,8 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,6,6,1,12 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,8,6,1,12 -END - -IDD_CONTINUE DIALOGEX 0, 0, 221, 58 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION -EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW -CAPTION "kTitle" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "kDefault",IDC_CONTINUE_DEFAULT,116,38,98,14 - LTEXT "kMessage",IDC_CONTINUE_MESSAGE,7,7,207,30 - PUSHBUTTON "kCancel",IDC_CONTINUE_CANCEL,7,38,98,14 -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// diff --git a/remoting/host/win/core.rc.jinja2 b/remoting/host/win/core.rc.jinja2 new file mode 100644 index 0000000..cf7c1807 --- /dev/null +++ b/remoting/host/win/core.rc.jinja2 @@ -0,0 +1,67 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <winresrc.h> +#include "remoting/host/win/core_resource.h" +#ifdef IDC_STATIC +#undef IDC_STATIC +#endif +#define IDC_STATIC (-1) + +{% for lang in languages %} + {% do SelectLanguage(lang) %} + +LANGUAGE {{ lang | GetPrimaryLanguage }}, {{ lang | GetSublanguage }} + +#if (BINARY == BINARY_CORE) + +STRINGTABLE +BEGIN + IDS_DISPLAY_SERVICE_NAME "{% trans %}DISPLAY_SERVICE_NAME{% endtrans %}" + IDS_SERVICE_DESCRIPTION "{% trans %}SERVICE_DESCRIPTION{% endtrans %}" + IDS_CONTROLLER_NAME "{% trans %}CONTROLLER_NAME{% endtrans %}" +END + +#endif // (BINARY == BINARY_CORE) + +IDD_VERIFY_CONFIG_DIALOG ICON "remoting/resources/chromoting.ico" + +IDD_VERIFY_CONFIG_DIALOG DIALOGEX 0, 0, 221, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUPWINDOW | WS_CAPTION +EXSTYLE 0 {% if IsRtlLanguage(lang) %} | WS_EX_LAYOUTRTL {% endif %} +CAPTION "{% trans %}PRODUCT_NAME{% endtrans %}" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "{% trans %}VERIFY_PIN_DIALOG_MESSAGE{% endtrans %}",IDC_MESSAGE,7,7,207,30 + LTEXT "{% trans %}VERIFY_PIN_DIALOG_EMAIL_LABEL{% endtrans %}",IDC_EMAIL_LABEL,7,38,50,30 + LTEXT "",IDC_EMAIL,60,38,110,30 + LTEXT "{% trans %}ASK_PIN_DIALOG_LABEL{% endtrans %}",IDC_PIN_LABEL,7,55,50,30 + EDITTEXT IDC_PIN,60,55,100,15,WS_TABSTOP | ES_PASSWORD | ES_NUMBER + DEFPUSHBUTTON "{% trans %}OK{% endtrans %}",IDOK,68,86,68,14,WS_TABSTOP + PUSHBUTTON "{% trans %}CANCEL{% endtrans %}",IDCANCEL,146,86,68,14,WS_TABSTOP +END + +IDD_DISCONNECT DIALOGEX 0, 0, 145, 24 +STYLE DS_SETFONT | WS_POPUP +EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW {% if IsRtlLanguage(lang) %} | WS_EX_LAYOUTRTL {% endif %} +FONT 9, "Microsoft Sans Serif", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "{% trans %}DISCONNECT_OTHER_BUTTON{% endtrans %}",IDC_DISCONNECT,68,5,70,14 + LTEXT "{% trans %}MESSAGE_SHARED{% endtrans %}",IDC_DISCONNECT_SHARINGWITH,18,7,43,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,6,6,1,12 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,8,6,1,12 +END + +IDD_CONTINUE DIALOGEX 0, 0, 221, 58 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW {% if IsRtlLanguage(lang) %} | WS_EX_LAYOUTRTL {% endif %} +CAPTION "kTitle" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "{% trans %}CONTINUE_BUTTON{% endtrans %}",IDC_CONTINUE_DEFAULT,116,38,98,14 + LTEXT "{% trans %}CONTINUE_PROMPT{% endtrans %}",IDC_CONTINUE_MESSAGE,7,7,207,30 + PUSHBUTTON "{% trans %}STOP_SHARING_BUTTON{% endtrans %}",IDC_CONTINUE_CANCEL,7,38,98,14 +END + +{% endfor %} diff --git a/remoting/host/win/core_resource.h b/remoting/host/win/core_resource.h index 4d93334..af27a0e 100644 --- a/remoting/host/win/core_resource.h +++ b/remoting/host/win/core_resource.h @@ -8,18 +8,18 @@ // // N.B. Values of |IDS_DISPLAY_SERVICE_NAME|, |IDS_SERVICE_DESCRIPTION|, -// |IDS_CONTROLLER| and |IDD_VERIFY_CONFIG_DIALOG| are hardcoded in +// |IDS_CONTROLLER_NAME| and |IDD_VERIFY_CONFIG_DIALOG| are hardcoded in // remoting/host/install/chromoting.wxs. Make sure the values below and in // the installation script match. #define IDS_DISPLAY_SERVICE_NAME 101 #define IDS_SERVICE_DESCRIPTION 102 -#define IDS_CONTROLLER 103 -#define IDD_VERIFY_CONFIG_DIALOG 104 -#define IDC_MESSAGE 105 -#define IDC_EMAIL 106 -#define IDC_PIN 107 -#define IDC_EMAIL_LABEL 108 -#define IDC_PIN_LABEL 109 +#define IDS_CONTROLLER_NAME 103 +#define IDD_VERIFY_CONFIG_DIALOG 104 +#define IDC_MESSAGE 105 +#define IDC_EMAIL 106 +#define IDC_PIN 107 +#define IDC_EMAIL_LABEL 108 +#define IDC_PIN_LABEL 109 #define IDD_DISCONNECT 110 #define IDD_CONTINUE 111 diff --git a/remoting/host/win/host_messages.mc.jinja2 b/remoting/host/win/host_messages.mc.jinja2 new file mode 100644 index 0000000..940b7bc --- /dev/null +++ b/remoting/host/win/host_messages.mc.jinja2 @@ -0,0 +1,89 @@ +; // Copyright 2013 The Chromium Authors. All rights reserved. +; // Use of this source code is governed by a BSD-style license that can be +; // found in the LICENSE file. + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR) + +FacilityNames=(Host=0x0:FACILITY_HOST) + +LanguageNames=( +{% for lang in languages %} +{{ lang | replace("-", "_") }}=0x{{ lang | GetLangId }}:MSG0{{ lang | GetLangId}} +{%- endfor %} +) + +; // The categories of events. +MessageIdTypedef=WORD + +MessageId=0x1 +SymbolicName=HOST_CATEGORY +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_CATEGORY{% endtrans %} +. +{%- endfor %} + +; // The message definitions. +MessageIdTypedef=DWORD + +MessageId=1 +Severity=Informational +Facility=Host +SymbolicName=MSG_HOST_CLIENT_CONNECTED +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_CLIENT_CONNECTED{% endtrans %} +. +{%- endfor %} + +MessageId=2 +Severity=Informational +Facility=Host +SymbolicName=MSG_HOST_CLIENT_DISCONNECTED +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_CLIENT_DISCONNECTED{% endtrans %} +. +{%- endfor %} + +MessageId=3 +Severity=Error +Facility=Host +SymbolicName=MSG_HOST_CLIENT_ACCESS_DENIED +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_CLIENT_ACCESS_DENIED{% endtrans %} +. +{%- endfor %} + +MessageId=4 +Severity=Informational +Facility=Host +SymbolicName=MSG_HOST_CLIENT_ROUTING_CHANGED +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_CLIENT_ROUTING_CHANGED{% endtrans %} +. +{%- endfor %} + +MessageId=5 +Severity=Informational +Facility=Host +SymbolicName=MSG_HOST_STARTED +{%- for lang in languages %} + {%- do SelectLanguage(lang) %} +Language={{ lang | replace("-", "_") }} +{% trans %}HOST_STARTED{% endtrans %} +. +{%- endfor %} + +; // This line makes sure that mc.exe does not complain about a single '.' at +; // the end of the file. diff --git a/remoting/host/win/remoting_core.ver b/remoting/host/win/remoting_core.ver deleted file mode 100644 index 33a6150..0000000 --- a/remoting/host/win/remoting_core.ver +++ /dev/null @@ -1,4 +0,0 @@ -BINARY=BINARY_CORE -FILE_TYPE=VFT_DLL -INTERNAL_NAME=remoting_core.dll -ORIGINAL_FILENAME=remoting_core.dll diff --git a/remoting/host/win/remoting_desktop.ver b/remoting/host/win/remoting_desktop.ver deleted file mode 100644 index 458c235..0000000 --- a/remoting/host/win/remoting_desktop.ver +++ /dev/null @@ -1,4 +0,0 @@ -BINARY=BINARY_DESKTOP -FILE_TYPE=VFT_APP -INTERNAL_NAME=remoting_desktop.exe -ORIGINAL_FILENAME=remoting_desktop.exe diff --git a/remoting/host/win/remoting_host.ver b/remoting/host/win/remoting_host.ver deleted file mode 100644 index 16cde44..0000000 --- a/remoting/host/win/remoting_host.ver +++ /dev/null @@ -1,4 +0,0 @@ -BINARY=BINARY_HOST_ME2ME -FILE_TYPE=VFT_APP -INTERNAL_NAME=remoting_host.exe -ORIGINAL_FILENAME=remoting_host.exe diff --git a/remoting/host/win/version.rc.jinja2 b/remoting/host/win/version.rc.jinja2 new file mode 100644 index 0000000..19ba83d --- /dev/null +++ b/remoting/host/win/version.rc.jinja2 @@ -0,0 +1,72 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <winresrc.h> +#ifdef IDC_STATIC +#undef IDC_STATIC +#endif +#define IDC_STATIC (-1) + +{% for lang in languages %} + {% do SelectLanguage(lang) %} + +LANGUAGE {{ lang | GetPrimaryLanguage }}, {{ lang | GetSublanguage }} + +VS_VERSION_INFO VERSIONINFO + FILEVERSION {{ MAJOR }},{{ REMOTING_PATCH }},{{ BUILD }},{{ PATCH }} + PRODUCTVERSION {{ MAJOR }},{{ REMOTING_PATCH }},{{ BUILD }},{{ PATCH }} + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L +#if (BINARY == BINARY_CORE) || (BINARY == BINARY_HOST_PLUGIN) + FILETYPE VFT_DLL +#else + FILETYPE VFT_APP +#endif + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "{{ lang | GetLangId }}{{ lang | GetCodepage }}" + BEGIN + VALUE "CompanyName", "{% trans %}COMPANY_NAME{% endtrans %}" + VALUE "FileVersion", "{{ MAJOR }}.{{ REMOTING_PATCH }}.{{ BUILD }}.{{ PATCH }}" + VALUE "LegalCopyright", "{% trans %}COPYRIGHT{% endtrans %}" + VALUE "ProductName", "{% trans %}PRODUCT_NAME{% endtrans %}" + VALUE "ProductVersion", "{{ MAJOR }}.{{ REMOTING_PATCH }}.{{ BUILD }}.{{ PATCH }}" + VALUE "LastChange", "{{ LASTCHANGE }}" + VALUE "Official Build", "{{ official_build }}" +#if (BINARY == BINARY_CORE) + VALUE "FileDescription", "{% trans %}REMOTING_CORE_DESCRIPTION{% endtrans %}" + VALUE "InternalName", "remoting_core.dll" + VALUE "OriginalFilename", "remoting_core.dll" +#elif (BINARY == BINARY_DESKTOP) + VALUE "FileDescription", "{% trans %}REMOTING_DESKTOP_DESCRIPTION{% endtrans %}" + VALUE "InternalName", "remoting_desktop.exe" + VALUE "OriginalFilename", "remoting_desktop.exe" +#elif (BINARY == BINARY_HOST_ME2ME) + VALUE "FileDescription", "{% trans %}REMOTING_HOST_DESCRIPTION{% endtrans %}" + VALUE "InternalName", "remoting_host.exe" + VALUE "OriginalFilename", "remoting_host.exe" +#elif (BINARY == BINARY_HOST_PLUGIN) + VALUE "FileDescription", "{% trans %}REMOTING_HOST_PLUGIN_DESCRIPTION{% endtrans %}" + VALUE "InternalName", "remoting_host_plugin.dll" + VALUE "OriginalFilename", "remoting_host_plugin.dll" + VALUE "MIMEType", "application/vnd.chromium.remoting-host" +#else +#error BINARY must be set to one of BINARY_XXX values. +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x{{ lang | GetLangId }}, {{ lang | GetCodepageDecimal }} + END +END + +{% endfor %} diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 94bb83d..b57338e 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -20,6 +20,8 @@ 'remoting_multi_process%': '<(remoting_multi_process)', 'remoting_rdp_session%': 1, + 'localize_py_path': 'tools/localize.py', + # The |major|, |build| and |patch| versions are inherited from Chrome. # Since Chrome's |minor| version is always '0', we replace it with a # Chromoting-specific patch version. @@ -98,6 +100,50 @@ 'rdp_desktop_session_clsid': '<!(python tools/uuidgen.py 2)', }], ], + 'remoting_languages': [ + '-l', 'ar', + '-l', 'bg', + '-l', 'ca', + '-l', 'cs', + '-l', 'da', + '-l', 'de', + '-l', 'el', + '-l', 'en', + '-l', 'en_GB', + '-l', 'es', + '-l', 'es_419', + '-l', 'et', + '-l', 'fi', + '-l', 'fil', + '-l', 'fr', + '-l', 'he', + '-l', 'hi', + '-l', 'hr', + '-l', 'hu', + '-l', 'id', + '-l', 'it', + '-l', 'ja', + '-l', 'ko', + '-l', 'lt', + '-l', 'lv', + '-l', 'nb', + '-l', 'nl', + '-l', 'pl', + '-l', 'pt_BR', + '-l', 'pt_PT', + '-l', 'ro', + '-l', 'ru', + '-l', 'sk', + '-l', 'sl', + '-l', 'sr', + '-l', 'sv', + '-l', 'th', + '-l', 'tr', + '-l', 'uk', + '-l', 'vi', + '-l', 'zh_CN', + '-l', 'zh_TW', + ], 'remoting_webapp_locale_files': [ '<(webapp_locale_dir)/ar/messages.json', '<(webapp_locale_dir)/bg/messages.json', @@ -249,6 +295,10 @@ 'target_defaults': { 'defines': [ + 'BINARY_CORE=1', + 'BINARY_DESKTOP=2', + 'BINARY_HOST_ME2ME=3', + 'BINARY_HOST_PLUGIN=4', ], 'include_dirs': [ '..', # Root of Chrome checkout @@ -659,18 +709,19 @@ 'product_extension': '<(host_plugin_extension)', 'product_prefix': '<(host_plugin_prefix)', 'dependencies': [ + '../net/net.gyp:net', + '../third_party/npapi/npapi.gyp:npapi', 'remoting_base', 'remoting_host', 'remoting_host_event_logger', 'remoting_host_logging', 'remoting_host_setup_base', 'remoting_jingle_glue', - '../net/net.gyp:net', - '../third_party/npapi/npapi.gyp:npapi', ], 'sources': [ + '<(SHARED_INTERMEDIATE_DIR)/remoting/core.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', 'base/dispatch_win.h', - 'host/win/core_resource.h', 'host/plugin/host_log_handler.cc', 'host/plugin/host_log_handler.h', 'host/plugin/host_plugin.cc', @@ -678,6 +729,7 @@ 'host/plugin/host_plugin_utils.h', 'host/plugin/host_script_object.cc', 'host/plugin/host_script_object.h', + 'host/win/core_resource.h', ], 'conditions': [ ['OS=="mac"', { @@ -715,18 +767,18 @@ }], # OS=="mac" [ 'OS=="win"', { 'defines': [ + 'BINARY=BINARY_HOST_PLUGIN', 'ISOLATION_AWARE_ENABLED=1', ], 'dependencies': [ 'remoting_lib_idl', + 'remoting_core_resources', 'remoting_version_resources', ], 'include_dirs': [ '<(INTERMEDIATE_DIR)', ], 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting/remoting_host_plugin_version.rc', - 'host/win/core.rc', 'host/plugin/host_plugin.def', ], }], @@ -1343,12 +1395,15 @@ 'target_name': 'remoting_console', 'type': 'executable', 'variables': { 'enable_wexit_time_destructors': 1, }, + 'defines': [ + 'BINARY=BINARY_HOST_ME2ME', + ], 'dependencies': [ 'remoting_core', 'remoting_version_resources', ], 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting/remoting_host_version.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', 'host/win/entry_point.cc', ], 'msvs_settings': { @@ -1401,6 +1456,7 @@ '_ATL_CSTRING_EXPLICIT_CONSTRUCTORS', '_ATL_NO_AUTOMATIC_NAMESPACE', '_ATL_NO_EXCEPTIONS', + 'BINARY=BINARY_CORE', 'DAEMON_CONTROLLER_CLSID="{<(daemon_controller_clsid)}"', 'RDP_DESKTOP_SESSION_CLSID="{<(rdp_desktop_session_clsid)}"', 'HOST_IMPLEMENTATION', @@ -1415,8 +1471,10 @@ '../ipc/ipc.gyp:ipc', '../net/net.gyp:net', '../third_party/webrtc/modules/modules.gyp:desktop_capture', + '../third_party/webrtc/modules/modules.gyp:desktop_capture', 'remoting_base', 'remoting_breakpad', + 'remoting_core_resources', 'remoting_host', 'remoting_host_event_logger', 'remoting_host_logging', @@ -1426,12 +1484,12 @@ 'remoting_me2me_host_static', 'remoting_protocol', 'remoting_version_resources', - '../third_party/webrtc/modules/modules.gyp:desktop_capture', ], 'sources': [ + '<(SHARED_INTERMEDIATE_DIR)/remoting/core.rc', '<(SHARED_INTERMEDIATE_DIR)/remoting/host/chromoting_lib.rc', '<(SHARED_INTERMEDIATE_DIR)/remoting/host/remoting_host_messages.rc', - '<(SHARED_INTERMEDIATE_DIR)/remoting/remoting_core_version.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', 'host/chromoting_messages.cc', 'host/chromoting_messages.h', 'host/config_file_watcher.cc', @@ -1462,7 +1520,6 @@ 'host/win/chromoting_module.cc', 'host/win/chromoting_module.h', 'host/win/core.cc', - 'host/win/core.rc', 'host/win/core_resource.h', 'host/win/elevated_controller.cc', 'host/win/elevated_controller.h', @@ -1535,15 +1592,52 @@ ], # actions }, # end of target 'remoting_core_manifest' { + 'target_name': 'remoting_core_resources', + 'type': 'none', + 'dependencies': [ + 'remoting_resources', + ], + 'hard_dependency': 1, + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + 'sources': [ + 'host/win/core.rc.jinja2' + ], + 'rules': [ + { + 'rule_name': 'version', + 'extension': 'jinja2', + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/remoting/core.rc' + ], + 'action': [ + 'python', + '<(localize_py_path)', + '<@(remoting_languages)', + '--messages_path', '<(webapp_locale_dir)', + '<(RULE_INPUT_PATH)', + '<@(_outputs)', + ], + 'message': 'Localizing the dialogs and strings' + }, + ], + }, # end of target 'remoting_core_resources' + { 'target_name': 'remoting_desktop', 'type': 'executable', 'variables': { 'enable_wexit_time_destructors': 1, }, + 'defines': [ + 'BINARY=BINARY_DESKTOP', + ], 'dependencies': [ 'remoting_core', 'remoting_version_resources', ], 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting/remoting_desktop_version.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', 'host/win/entry_point.cc', ], 'msvs_settings': { @@ -1602,12 +1696,15 @@ 'product_name': 'remoting_host', 'type': 'executable', 'variables': { 'enable_wexit_time_destructors': 1, }, + 'defines': [ + 'BINARY=BINARY_HOST_ME2ME', + ], 'dependencies': [ 'remoting_core', 'remoting_version_resources', ], 'sources': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting/remoting_host_version.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', 'host/win/entry_point.cc', ], 'msvs_settings': { @@ -1653,7 +1750,40 @@ }, ], # actions }, # end of target 'remoting_host_manifest' - + { + 'target_name': 'remoting_host_messages', + 'type': 'none', + 'dependencies': [ + 'remoting_resources', + ], + 'hard_dependency': 1, + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + 'sources': [ + 'host/win/host_messages.mc.jinja2' + ], + 'rules': [ + { + 'rule_name': 'localize', + 'extension': 'jinja2', + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/remoting/host/remoting_host_messages.mc', + ], + 'action': [ + 'python', + '<(localize_py_path)', + '<@(remoting_languages)', + '--messages_path', '<(webapp_locale_dir)', + '<(RULE_INPUT_PATH)', + '<@(_outputs)', + ], + 'message': 'Localizing the event log messages' + }, + ], + }, # end of target 'remoting_host_messages' { 'target_name': 'remoting_host_plugin_manifest', 'type': 'none', @@ -1688,70 +1818,58 @@ ], # actions }, # end of target 'remoting_host_plugin_manifest' - # Generates the version information resources for the Windows binaries. - # The .RC files are generated from the "version.rc.version" template and - # placed in the "<(SHARED_INTERMEDIATE_DIR)/remoting" folder. + # Generates localized the version information resources for the Windows + # binaries. # The substitution strings are taken from: # - build/util/LASTCHANGE - the last source code revision. # - chrome/VERSION - the major, build & patch versions. # - remoting/VERSION - the chromoting patch version (and overrides # for chrome/VERSION). - # - (branding_path) - UI/localizable strings. - # - xxx.ver - per-binary non-localizable strings such as the binary - # name. + # - translated webapp strings { 'target_name': 'remoting_version_resources', 'type': 'none', - 'inputs': [ - '<(branding_path)', - 'version.rc.version', - '<(DEPTH)/build/util/LASTCHANGE', - '<(remoting_version_path)', - '<(chrome_version_path)', + 'dependencies': [ + 'remoting_resources', ], + 'hard_dependency': 1, 'direct_dependent_settings': { 'include_dirs': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting', + '<(SHARED_INTERMEDIATE_DIR)', ], }, 'sources': [ - 'host/plugin/remoting_host_plugin.ver', - 'host/win/remoting_core.ver', - 'host/win/remoting_desktop.ver', - 'host/win/remoting_host.ver', + 'host/win/version.rc.jinja2' ], 'rules': [ { 'rule_name': 'version', - 'extension': 'ver', + 'extension': 'jinja2', 'variables': { 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', - 'template_input_path': 'version.rc.version', }, 'inputs': [ - '<(branding_path)', '<(chrome_version_path)', '<(lastchange_path)', '<(remoting_version_path)', - '<(template_input_path)', ], 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/remoting/<(RULE_INPUT_ROOT)_version.rc', + '<(SHARED_INTERMEDIATE_DIR)/remoting/version.rc', ], 'action': [ 'python', - '<(version_py_path)', - '-f', '<(RULE_INPUT_PATH)', - '-f', '<(chrome_version_path)', + '<(localize_py_path)', + '<@(remoting_languages)', + '-i', '<(chrome_version_path)', # |remoting_version_path| must be after |chrome_version_path| # because it can contain overrides for the version numbers. - '-f', '<(remoting_version_path)', - '-f', '<(branding_path)', - '-f', '<(lastchange_path)', - '<(template_input_path)', + '-i', '<(remoting_version_path)', + '-i', '<(lastchange_path)', + '--messages_path', '<(webapp_locale_dir)', + '<(RULE_INPUT_PATH)', '<@(_outputs)', ], - 'message': 'Generating version information in <@(_outputs)' + 'message': 'Localizing the version information' }, ], }, # end of target 'remoting_version_resources' @@ -1977,10 +2095,13 @@ ], 'conditions': [ ['OS=="win"', { - 'sources': [ - 'host/remoting_host_messages.mc', + 'dependencies': [ + 'remoting_host_messages', ], 'output_dir': '<(SHARED_INTERMEDIATE_DIR)/remoting/host', + 'sources': [ + '<(_output_dir)/remoting_host_messages.mc', + ], 'include_dirs': [ '<(_output_dir)', ], @@ -1989,8 +2110,8 @@ '<(_output_dir)', ], }, - # Rule to run the message compiler. 'rules': [ + # Rule to run the message compiler. { 'rule_name': 'message_compiler', 'extension': 'mc', @@ -2004,6 +2125,7 @@ 'mc.exe', '-h', '<(_output_dir)', '-r', '<(_output_dir)/.', + '-u', '<(RULE_INPUT_PATH)', ], 'process_outputs_as_sources': 1, @@ -2166,6 +2288,9 @@ 'sources': [ 'base/resources_unittest.cc', 'host/plugin/host_script_object.cc', + 'host/win/core.rc.jinja2', + 'host/win/host_messages.mc.jinja2', + 'host/win/version.rc.jinja2', 'webapp/butter_bar.js', 'webapp/client_screen.js', 'webapp/error.js', diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index 2d0c3c6..18c3625 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd @@ -199,6 +199,24 @@ <message name="IDR_SURVEY_INVITATION" desc="Invitation to the user to participate in a user survey for Chrome Remote Desktop"> Want to help improve Chrome Remote Desktop? <ph name="LINK_BEGIN">$1<ex><a href=http://goo.gl/njH2q></ex></ph>Take the survey.<ph name="LINK_END">$2<ex></a></ex></ph> </message> + <message name="IDR_COMPANY_NAME" desc="The company name specified in the version information of each Chrome Remote Desktop Host executable."> + Google Inc. + </message> + <message name="IDR_COPYRIGHT" desc="The copyright message specified in the version information of each Chrome Remote Desktop Host executable. It should be updated every year."> + Copyright 2013 Google Inc. All Rights Reserved. + </message> + <message name="IDR_DISPLAY_SERVICE_NAME" desc="The name of the Windows service installed by Chrome Remote Desktop."> + Chrome Remote Desktop Service + </message> + <message name="IDR_SERVICE_DESCRIPTION" desc="The description of the Windows service installed by Chrome Remote Desktop."> + This service enables incoming connections from Chrome Remote Desktop clients. + </message> + <message name="IDR_CONTROLLER_NAME" desc="The name of the component to be elevated shown on the UAC prompt when enabling or disabling Chrome Remote Desktop Host."> + Chrome Remote Desktop Host Controller + </message> + <message name="IDR_VERIFY_PIN_DIALOG_MESSAGE" desc="The message displayed by the PIN verification dialog."> + Please confirm your account and PIN below to allow access by Chrome Remote Desktop. + </message> </if> <if expr="not pp_ifdef('_google_chrome')"> @@ -265,6 +283,24 @@ <message name="IDR_SURVEY_INVITATION" desc="Invitation to the user to participate in a user survey for Chromoting"> Want to help improve Chromoting? <ph name="LINK_BEGIN">$1<ex><a href=http://goo.gl/njH2q></ex></ph>Take the survey.<ph name="LINK_END">$2<ex></a></ex></ph> </message> + <message name="IDR_COMPANY_NAME" desc="The company name specified in the version information of each Chromoting Host executable."> + The Chromium Authors + </message> + <message name="IDR_COPYRIGHT" desc="The copyright message specified in the version information of each Chromoting Host executable. It should be updated every year."> + Copyright 2013 The Chromium Authors. All Rights Reserved. + </message> + <message name="IDR_DISPLAY_SERVICE_NAME" desc="The name of the Windows service installed by Chromoting."> + Chromoting Service + </message> + <message name="IDR_SERVICE_DESCRIPTION" desc="The description of the Windows service installed by Chromoting."> + This service enables incoming connections from Chromoting clients. + </message> + <message name="IDR_CONTROLLER_NAME" desc="The name of the component to be elevated shown on the UAC prompt when enabling or disabling Chromoting Host."> + Chromoting Host Controller + </message> + <message name="IDR_VERIFY_PIN_DIALOG_MESSAGE" desc="The message displayed by the PIN verification dialog."> + Please confirm your account and PIN below to allow access by Chromoting. + </message> </if> <message desc="Label for the access code entry box. This is where the client user enters the code that permits access to the host." name="IDR_ACCESS_CODE"> @@ -555,6 +591,39 @@ <message name="IDR_HANGOUTS_INVITATION" desc="Text for the invitation to try Remote Desktop app in Hangouts."> Want to help someone while having a video chat with them too? Try <ph name="LINK_BEGIN">$1<ex><a href=https://plus.google.com/hangouts></ex></ph> Remote Desktop in Google Hangouts<ph name="LINK_END">$2<ex></a></ex></ph>. </message> + <message name="IDR_REMOTING_CORE_DESCRIPTION" desc="The file description specified in the version information of remoting_core.dll."> + Core Library + </message> + <message name="IDR_REMOTING_DESKTOP_DESCRIPTION" desc="The file description specified in the version information of remoting_desktop.exe."> + Desktop Integration Process + </message> + <message name="IDR_REMOTING_HOST_DESCRIPTION" desc="The file description specified in the version information of remoting_host.exe."> + Host Process + </message> + <message name="IDR_REMOTING_HOST_PLUGIN_DESCRIPTION" desc="The file description specified in the version information of remoting_host_plugin.dll."> + Allow another user to access your computer securely over the Internet. + </message> + <message name="IDR_VERIFY_PIN_DIALOG_EMAIL_LABEL" desc="The message displayed by the PIN verification dialog."> + Account + </message> + <message name="IDR_HOST_CATEGORY" desc="Name of the message category assigned to all messages written to the EventLog by Chromoting Host."> + Host + </message> + <message name="IDR_HOST_CLIENT_CONNECTED" desc="The message reported to the EventLog by Chromoting Host every time a client connects."> + Client connected: <ph name="CLIENT_USERNAME">%1<ex>client@email.com</ex></ph>. + </message> + <message name="IDR_HOST_CLIENT_DISCONNECTED" desc="The message reported to the EventLog by Chromoting Host every time a client disconnects."> + Client disconnected: <ph name="CLIENT_USERNAME">%1<ex>client@email.com</ex></ph>. + </message> + <message name="IDR_HOST_CLIENT_ACCESS_DENIED" desc="The message reported to the EventLog by Chromoting Host every time the host denies access to a client."> + Access denied for client: <ph name="CLIENT_USERNAME">%1<ex>client@email.com</ex></ph>. + </message> + <message name="IDR_HOST_CLIENT_ROUTING_CHANGED" desc="The message reported to the EventLog by Chromoting Host every time a channel (a logical connection) between the client and the host is established. Multiple channels can be multiplexed over the same underlying protocol connection. The IP addresses and connection type of the underlying connection are reported. The channel and connection types are reported as opaque strings which should not be translated."> + Channel IP for client: <ph name="CLIENT_GAIA_IDENTIFIER">%1<ex>client@email.com/TalkGadgetABCDABCD</ex></ph> ip='<ph name="CLIENT_IP_ADDRESS_AND_PORT">%2<ex>127.0.0.1:1000</ex></ph>' host_ip='<ph name="HOST_IP_ADDRESS_AND_PORT">%3<ex>127.0.0.1:2000</ex></ph>' channel='<ph name="CHANNEL_TYPE">%4<ex>mux</ex></ph>' connection='<ph name="CONNECTION_TYPE">%5<ex>direct</ex></ph>'. + </message> + <message name="IDR_HOST_STARTED" desc="The message reported to the EventLog by Chromoting Host every time it is started."> + Host started for user: <ph name="HOST_USERNAME">%1<ex>host@email.com</ex></ph>. + </message> </messages> </release> </grit> diff --git a/remoting/tools/DEPS b/remoting/tools/DEPS index c3c25f4..324c396 100644 --- a/remoting/tools/DEPS +++ b/remoting/tools/DEPS @@ -1,3 +1,4 @@ include_rules = [ "+remoting/host", + "+third_party/jinja2", ] diff --git a/remoting/tools/localize.py b/remoting/tools/localize.py new file mode 100755 index 0000000..fa2d732 --- /dev/null +++ b/remoting/tools/localize.py @@ -0,0 +1,718 @@ +#!/usr/bin/env python +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +localize.py -- Generates an output file from the given template replacing +variables and localizing strings. + +The script uses Jinja2 template processing library (src/third_party/jinja2). +Variables available to the templates: + - |languages| - the list of languages passed on the command line. ('-l'). + - Each KEY=VALUE define ('-d') can be accesses as |KEY|. + - |official_build| is set to '1' when CHROME_BUILD_TYPE environment variable + is set to "_official". + +Filters: + - GetCodepage - returns the code page for the given language. + - GetCodepageDecimal same as GetCodepage, but returns a decimal value. + - GetLangId - returns Win32 LANGID. + - GetPrimaryLanguage - returns a named Win32 constant specifing the primary + language ID. + - GetSublanguage - returns a named Win32 constant specifing the sublanguage + ID. + +Globals: + - SelectLanguage(language) - allows to select the language to the used by + {% trans %}{% endtrans %} statements. + +""" + +import io +import json +from optparse import OptionParser +import os +import sys + +# Win32 primary languages IDs. +_LANGUAGE_PRIMARY = { + 'LANG_NEUTRAL' : 0x00, + 'LANG_INVARIANT' : 0x7f, + 'LANG_AFRIKAANS' : 0x36, + 'LANG_ALBANIAN' : 0x1c, + 'LANG_ALSATIAN' : 0x84, + 'LANG_AMHARIC' : 0x5e, + 'LANG_ARABIC' : 0x01, + 'LANG_ARMENIAN' : 0x2b, + 'LANG_ASSAMESE' : 0x4d, + 'LANG_AZERI' : 0x2c, + 'LANG_BASHKIR' : 0x6d, + 'LANG_BASQUE' : 0x2d, + 'LANG_BELARUSIAN' : 0x23, + 'LANG_BENGALI' : 0x45, + 'LANG_BRETON' : 0x7e, + 'LANG_BOSNIAN' : 0x1a, + 'LANG_BULGARIAN' : 0x02, + 'LANG_CATALAN' : 0x03, + 'LANG_CHINESE' : 0x04, + 'LANG_CORSICAN' : 0x83, + 'LANG_CROATIAN' : 0x1a, + 'LANG_CZECH' : 0x05, + 'LANG_DANISH' : 0x06, + 'LANG_DARI' : 0x8c, + 'LANG_DIVEHI' : 0x65, + 'LANG_DUTCH' : 0x13, + 'LANG_ENGLISH' : 0x09, + 'LANG_ESTONIAN' : 0x25, + 'LANG_FAEROESE' : 0x38, + 'LANG_FILIPINO' : 0x64, + 'LANG_FINNISH' : 0x0b, + 'LANG_FRENCH' : 0x0c, + 'LANG_FRISIAN' : 0x62, + 'LANG_GALICIAN' : 0x56, + 'LANG_GEORGIAN' : 0x37, + 'LANG_GERMAN' : 0x07, + 'LANG_GREEK' : 0x08, + 'LANG_GREENLANDIC' : 0x6f, + 'LANG_GUJARATI' : 0x47, + 'LANG_HAUSA' : 0x68, + 'LANG_HEBREW' : 0x0d, + 'LANG_HINDI' : 0x39, + 'LANG_HUNGARIAN' : 0x0e, + 'LANG_ICELANDIC' : 0x0f, + 'LANG_IGBO' : 0x70, + 'LANG_INDONESIAN' : 0x21, + 'LANG_INUKTITUT' : 0x5d, + 'LANG_IRISH' : 0x3c, + 'LANG_ITALIAN' : 0x10, + 'LANG_JAPANESE' : 0x11, + 'LANG_KANNADA' : 0x4b, + 'LANG_KASHMIRI' : 0x60, + 'LANG_KAZAK' : 0x3f, + 'LANG_KHMER' : 0x53, + 'LANG_KICHE' : 0x86, + 'LANG_KINYARWANDA' : 0x87, + 'LANG_KONKANI' : 0x57, + 'LANG_KOREAN' : 0x12, + 'LANG_KYRGYZ' : 0x40, + 'LANG_LAO' : 0x54, + 'LANG_LATVIAN' : 0x26, + 'LANG_LITHUANIAN' : 0x27, + 'LANG_LOWER_SORBIAN' : 0x2e, + 'LANG_LUXEMBOURGISH' : 0x6e, + 'LANG_MACEDONIAN' : 0x2f, + 'LANG_MALAY' : 0x3e, + 'LANG_MALAYALAM' : 0x4c, + 'LANG_MALTESE' : 0x3a, + 'LANG_MANIPURI' : 0x58, + 'LANG_MAORI' : 0x81, + 'LANG_MAPUDUNGUN' : 0x7a, + 'LANG_MARATHI' : 0x4e, + 'LANG_MOHAWK' : 0x7c, + 'LANG_MONGOLIAN' : 0x50, + 'LANG_NEPALI' : 0x61, + 'LANG_NORWEGIAN' : 0x14, + 'LANG_OCCITAN' : 0x82, + 'LANG_ORIYA' : 0x48, + 'LANG_PASHTO' : 0x63, + 'LANG_PERSIAN' : 0x29, + 'LANG_POLISH' : 0x15, + 'LANG_PORTUGUESE' : 0x16, + 'LANG_PUNJABI' : 0x46, + 'LANG_QUECHUA' : 0x6b, + 'LANG_ROMANIAN' : 0x18, + 'LANG_ROMANSH' : 0x17, + 'LANG_RUSSIAN' : 0x19, + 'LANG_SAMI' : 0x3b, + 'LANG_SANSKRIT' : 0x4f, + 'LANG_SCOTTISH_GAELIC' : 0x91, + 'LANG_SERBIAN' : 0x1a, + 'LANG_SINDHI' : 0x59, + 'LANG_SINHALESE' : 0x5b, + 'LANG_SLOVAK' : 0x1b, + 'LANG_SLOVENIAN' : 0x24, + 'LANG_SOTHO' : 0x6c, + 'LANG_SPANISH' : 0x0a, + 'LANG_SWAHILI' : 0x41, + 'LANG_SWEDISH' : 0x1d, + 'LANG_SYRIAC' : 0x5a, + 'LANG_TAJIK' : 0x28, + 'LANG_TAMAZIGHT' : 0x5f, + 'LANG_TAMIL' : 0x49, + 'LANG_TATAR' : 0x44, + 'LANG_TELUGU' : 0x4a, + 'LANG_THAI' : 0x1e, + 'LANG_TIBETAN' : 0x51, + 'LANG_TIGRIGNA' : 0x73, + 'LANG_TSWANA' : 0x32, + 'LANG_TURKISH' : 0x1f, + 'LANG_TURKMEN' : 0x42, + 'LANG_UIGHUR' : 0x80, + 'LANG_UKRAINIAN' : 0x22, + 'LANG_UPPER_SORBIAN' : 0x2e, + 'LANG_URDU' : 0x20, + 'LANG_UZBEK' : 0x43, + 'LANG_VIETNAMESE' : 0x2a, + 'LANG_WELSH' : 0x52, + 'LANG_WOLOF' : 0x88, + 'LANG_XHOSA' : 0x34, + 'LANG_YAKUT' : 0x85, + 'LANG_YI' : 0x78, + 'LANG_YORUBA' : 0x6a, + 'LANG_ZULU' : 0x35, +} + + +# Win32 sublanguage IDs. +_LANGUAGE_SUB = { + 'SUBLANG_NEUTRAL' : 0x00, + 'SUBLANG_DEFAULT' : 0x01, + 'SUBLANG_SYS_DEFAULT' : 0x02, + 'SUBLANG_CUSTOM_DEFAULT' : 0x03, + 'SUBLANG_CUSTOM_UNSPECIFIED' : 0x04, + 'SUBLANG_UI_CUSTOM_DEFAULT' : 0x05, + 'SUBLANG_AFRIKAANS_SOUTH_AFRICA' : 0x01, + 'SUBLANG_ALBANIAN_ALBANIA' : 0x01, + 'SUBLANG_ALSATIAN_FRANCE' : 0x01, + 'SUBLANG_AMHARIC_ETHIOPIA' : 0x01, + 'SUBLANG_ARABIC_SAUDI_ARABIA' : 0x01, + 'SUBLANG_ARABIC_IRAQ' : 0x02, + 'SUBLANG_ARABIC_EGYPT' : 0x03, + 'SUBLANG_ARABIC_LIBYA' : 0x04, + 'SUBLANG_ARABIC_ALGERIA' : 0x05, + 'SUBLANG_ARABIC_MOROCCO' : 0x06, + 'SUBLANG_ARABIC_TUNISIA' : 0x07, + 'SUBLANG_ARABIC_OMAN' : 0x08, + 'SUBLANG_ARABIC_YEMEN' : 0x09, + 'SUBLANG_ARABIC_SYRIA' : 0x0a, + 'SUBLANG_ARABIC_JORDAN' : 0x0b, + 'SUBLANG_ARABIC_LEBANON' : 0x0c, + 'SUBLANG_ARABIC_KUWAIT' : 0x0d, + 'SUBLANG_ARABIC_UAE' : 0x0e, + 'SUBLANG_ARABIC_BAHRAIN' : 0x0f, + 'SUBLANG_ARABIC_QATAR' : 0x10, + 'SUBLANG_ARMENIAN_ARMENIA' : 0x01, + 'SUBLANG_ASSAMESE_INDIA' : 0x01, + 'SUBLANG_AZERI_LATIN' : 0x01, + 'SUBLANG_AZERI_CYRILLIC' : 0x02, + 'SUBLANG_BASHKIR_RUSSIA' : 0x01, + 'SUBLANG_BASQUE_BASQUE' : 0x01, + 'SUBLANG_BELARUSIAN_BELARUS' : 0x01, + 'SUBLANG_BENGALI_INDIA' : 0x01, + 'SUBLANG_BENGALI_BANGLADESH' : 0x02, + 'SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x05, + 'SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC' : 0x08, + 'SUBLANG_BRETON_FRANCE' : 0x01, + 'SUBLANG_BULGARIAN_BULGARIA' : 0x01, + 'SUBLANG_CATALAN_CATALAN' : 0x01, + 'SUBLANG_CHINESE_TRADITIONAL' : 0x01, + 'SUBLANG_CHINESE_SIMPLIFIED' : 0x02, + 'SUBLANG_CHINESE_HONGKONG' : 0x03, + 'SUBLANG_CHINESE_SINGAPORE' : 0x04, + 'SUBLANG_CHINESE_MACAU' : 0x05, + 'SUBLANG_CORSICAN_FRANCE' : 0x01, + 'SUBLANG_CZECH_CZECH_REPUBLIC' : 0x01, + 'SUBLANG_CROATIAN_CROATIA' : 0x01, + 'SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x04, + 'SUBLANG_DANISH_DENMARK' : 0x01, + 'SUBLANG_DARI_AFGHANISTAN' : 0x01, + 'SUBLANG_DIVEHI_MALDIVES' : 0x01, + 'SUBLANG_DUTCH' : 0x01, + 'SUBLANG_DUTCH_BELGIAN' : 0x02, + 'SUBLANG_ENGLISH_US' : 0x01, + 'SUBLANG_ENGLISH_UK' : 0x02, + 'SUBLANG_ENGLISH_AUS' : 0x03, + 'SUBLANG_ENGLISH_CAN' : 0x04, + 'SUBLANG_ENGLISH_NZ' : 0x05, + 'SUBLANG_ENGLISH_EIRE' : 0x06, + 'SUBLANG_ENGLISH_SOUTH_AFRICA' : 0x07, + 'SUBLANG_ENGLISH_JAMAICA' : 0x08, + 'SUBLANG_ENGLISH_CARIBBEAN' : 0x09, + 'SUBLANG_ENGLISH_BELIZE' : 0x0a, + 'SUBLANG_ENGLISH_TRINIDAD' : 0x0b, + 'SUBLANG_ENGLISH_ZIMBABWE' : 0x0c, + 'SUBLANG_ENGLISH_PHILIPPINES' : 0x0d, + 'SUBLANG_ENGLISH_INDIA' : 0x10, + 'SUBLANG_ENGLISH_MALAYSIA' : 0x11, + 'SUBLANG_ENGLISH_SINGAPORE' : 0x12, + 'SUBLANG_ESTONIAN_ESTONIA' : 0x01, + 'SUBLANG_FAEROESE_FAROE_ISLANDS' : 0x01, + 'SUBLANG_FILIPINO_PHILIPPINES' : 0x01, + 'SUBLANG_FINNISH_FINLAND' : 0x01, + 'SUBLANG_FRENCH' : 0x01, + 'SUBLANG_FRENCH_BELGIAN' : 0x02, + 'SUBLANG_FRENCH_CANADIAN' : 0x03, + 'SUBLANG_FRENCH_SWISS' : 0x04, + 'SUBLANG_FRENCH_LUXEMBOURG' : 0x05, + 'SUBLANG_FRENCH_MONACO' : 0x06, + 'SUBLANG_FRISIAN_NETHERLANDS' : 0x01, + 'SUBLANG_GALICIAN_GALICIAN' : 0x01, + 'SUBLANG_GEORGIAN_GEORGIA' : 0x01, + 'SUBLANG_GERMAN' : 0x01, + 'SUBLANG_GERMAN_SWISS' : 0x02, + 'SUBLANG_GERMAN_AUSTRIAN' : 0x03, + 'SUBLANG_GERMAN_LUXEMBOURG' : 0x04, + 'SUBLANG_GERMAN_LIECHTENSTEIN' : 0x05, + 'SUBLANG_GREEK_GREECE' : 0x01, + 'SUBLANG_GREENLANDIC_GREENLAND' : 0x01, + 'SUBLANG_GUJARATI_INDIA' : 0x01, + 'SUBLANG_HAUSA_NIGERIA_LATIN' : 0x01, + 'SUBLANG_HEBREW_ISRAEL' : 0x01, + 'SUBLANG_HINDI_INDIA' : 0x01, + 'SUBLANG_HUNGARIAN_HUNGARY' : 0x01, + 'SUBLANG_ICELANDIC_ICELAND' : 0x01, + 'SUBLANG_IGBO_NIGERIA' : 0x01, + 'SUBLANG_INDONESIAN_INDONESIA' : 0x01, + 'SUBLANG_INUKTITUT_CANADA' : 0x01, + 'SUBLANG_INUKTITUT_CANADA_LATIN' : 0x02, + 'SUBLANG_IRISH_IRELAND' : 0x02, + 'SUBLANG_ITALIAN' : 0x01, + 'SUBLANG_ITALIAN_SWISS' : 0x02, + 'SUBLANG_JAPANESE_JAPAN' : 0x01, + 'SUBLANG_KANNADA_INDIA' : 0x01, + 'SUBLANG_KASHMIRI_SASIA' : 0x02, + 'SUBLANG_KASHMIRI_INDIA' : 0x02, + 'SUBLANG_KAZAK_KAZAKHSTAN' : 0x01, + 'SUBLANG_KHMER_CAMBODIA' : 0x01, + 'SUBLANG_KICHE_GUATEMALA' : 0x01, + 'SUBLANG_KINYARWANDA_RWANDA' : 0x01, + 'SUBLANG_KONKANI_INDIA' : 0x01, + 'SUBLANG_KOREAN' : 0x01, + 'SUBLANG_KYRGYZ_KYRGYZSTAN' : 0x01, + 'SUBLANG_LAO_LAO' : 0x01, + 'SUBLANG_LATVIAN_LATVIA' : 0x01, + 'SUBLANG_LITHUANIAN' : 0x01, + 'SUBLANG_LOWER_SORBIAN_GERMANY' : 0x02, + 'SUBLANG_LUXEMBOURGISH_LUXEMBOURG' : 0x01, + 'SUBLANG_MACEDONIAN_MACEDONIA' : 0x01, + 'SUBLANG_MALAY_MALAYSIA' : 0x01, + 'SUBLANG_MALAY_BRUNEI_DARUSSALAM' : 0x02, + 'SUBLANG_MALAYALAM_INDIA' : 0x01, + 'SUBLANG_MALTESE_MALTA' : 0x01, + 'SUBLANG_MAORI_NEW_ZEALAND' : 0x01, + 'SUBLANG_MAPUDUNGUN_CHILE' : 0x01, + 'SUBLANG_MARATHI_INDIA' : 0x01, + 'SUBLANG_MOHAWK_MOHAWK' : 0x01, + 'SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA' : 0x01, + 'SUBLANG_MONGOLIAN_PRC' : 0x02, + 'SUBLANG_NEPALI_INDIA' : 0x02, + 'SUBLANG_NEPALI_NEPAL' : 0x01, + 'SUBLANG_NORWEGIAN_BOKMAL' : 0x01, + 'SUBLANG_NORWEGIAN_NYNORSK' : 0x02, + 'SUBLANG_OCCITAN_FRANCE' : 0x01, + 'SUBLANG_ORIYA_INDIA' : 0x01, + 'SUBLANG_PASHTO_AFGHANISTAN' : 0x01, + 'SUBLANG_PERSIAN_IRAN' : 0x01, + 'SUBLANG_POLISH_POLAND' : 0x01, + 'SUBLANG_PORTUGUESE' : 0x02, + 'SUBLANG_PORTUGUESE_BRAZILIAN' : 0x01, + 'SUBLANG_PUNJABI_INDIA' : 0x01, + 'SUBLANG_QUECHUA_BOLIVIA' : 0x01, + 'SUBLANG_QUECHUA_ECUADOR' : 0x02, + 'SUBLANG_QUECHUA_PERU' : 0x03, + 'SUBLANG_ROMANIAN_ROMANIA' : 0x01, + 'SUBLANG_ROMANSH_SWITZERLAND' : 0x01, + 'SUBLANG_RUSSIAN_RUSSIA' : 0x01, + 'SUBLANG_SAMI_NORTHERN_NORWAY' : 0x01, + 'SUBLANG_SAMI_NORTHERN_SWEDEN' : 0x02, + 'SUBLANG_SAMI_NORTHERN_FINLAND' : 0x03, + 'SUBLANG_SAMI_LULE_NORWAY' : 0x04, + 'SUBLANG_SAMI_LULE_SWEDEN' : 0x05, + 'SUBLANG_SAMI_SOUTHERN_NORWAY' : 0x06, + 'SUBLANG_SAMI_SOUTHERN_SWEDEN' : 0x07, + 'SUBLANG_SAMI_SKOLT_FINLAND' : 0x08, + 'SUBLANG_SAMI_INARI_FINLAND' : 0x09, + 'SUBLANG_SANSKRIT_INDIA' : 0x01, + 'SUBLANG_SCOTTISH_GAELIC' : 0x01, + 'SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x06, + 'SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC' : 0x07, + 'SUBLANG_SERBIAN_MONTENEGRO_LATIN' : 0x0b, + 'SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC' : 0x0c, + 'SUBLANG_SERBIAN_SERBIA_LATIN' : 0x09, + 'SUBLANG_SERBIAN_SERBIA_CYRILLIC' : 0x0a, + 'SUBLANG_SERBIAN_CROATIA' : 0x01, + 'SUBLANG_SERBIAN_LATIN' : 0x02, + 'SUBLANG_SERBIAN_CYRILLIC' : 0x03, + 'SUBLANG_SINDHI_INDIA' : 0x01, + 'SUBLANG_SINDHI_PAKISTAN' : 0x02, + 'SUBLANG_SINDHI_AFGHANISTAN' : 0x02, + 'SUBLANG_SINHALESE_SRI_LANKA' : 0x01, + 'SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA' : 0x01, + 'SUBLANG_SLOVAK_SLOVAKIA' : 0x01, + 'SUBLANG_SLOVENIAN_SLOVENIA' : 0x01, + 'SUBLANG_SPANISH' : 0x01, + 'SUBLANG_SPANISH_MEXICAN' : 0x02, + 'SUBLANG_SPANISH_MODERN' : 0x03, + 'SUBLANG_SPANISH_GUATEMALA' : 0x04, + 'SUBLANG_SPANISH_COSTA_RICA' : 0x05, + 'SUBLANG_SPANISH_PANAMA' : 0x06, + 'SUBLANG_SPANISH_DOMINICAN_REPUBLIC' : 0x07, + 'SUBLANG_SPANISH_VENEZUELA' : 0x08, + 'SUBLANG_SPANISH_COLOMBIA' : 0x09, + 'SUBLANG_SPANISH_PERU' : 0x0a, + 'SUBLANG_SPANISH_ARGENTINA' : 0x0b, + 'SUBLANG_SPANISH_ECUADOR' : 0x0c, + 'SUBLANG_SPANISH_CHILE' : 0x0d, + 'SUBLANG_SPANISH_URUGUAY' : 0x0e, + 'SUBLANG_SPANISH_PARAGUAY' : 0x0f, + 'SUBLANG_SPANISH_BOLIVIA' : 0x10, + 'SUBLANG_SPANISH_EL_SALVADOR' : 0x11, + 'SUBLANG_SPANISH_HONDURAS' : 0x12, + 'SUBLANG_SPANISH_NICARAGUA' : 0x13, + 'SUBLANG_SPANISH_PUERTO_RICO' : 0x14, + 'SUBLANG_SPANISH_US' : 0x15, + 'SUBLANG_SWAHILI_KENYA' : 0x01, + 'SUBLANG_SWEDISH' : 0x01, + 'SUBLANG_SWEDISH_FINLAND' : 0x02, + 'SUBLANG_SYRIAC_SYRIA' : 0x01, + 'SUBLANG_TAJIK_TAJIKISTAN' : 0x01, + 'SUBLANG_TAMAZIGHT_ALGERIA_LATIN' : 0x02, + 'SUBLANG_TAMIL_INDIA' : 0x01, + 'SUBLANG_TATAR_RUSSIA' : 0x01, + 'SUBLANG_TELUGU_INDIA' : 0x01, + 'SUBLANG_THAI_THAILAND' : 0x01, + 'SUBLANG_TIBETAN_PRC' : 0x01, + 'SUBLANG_TIGRIGNA_ERITREA' : 0x02, + 'SUBLANG_TSWANA_SOUTH_AFRICA' : 0x01, + 'SUBLANG_TURKISH_TURKEY' : 0x01, + 'SUBLANG_TURKMEN_TURKMENISTAN' : 0x01, + 'SUBLANG_UIGHUR_PRC' : 0x01, + 'SUBLANG_UKRAINIAN_UKRAINE' : 0x01, + 'SUBLANG_UPPER_SORBIAN_GERMANY' : 0x01, + 'SUBLANG_URDU_PAKISTAN' : 0x01, + 'SUBLANG_URDU_INDIA' : 0x02, + 'SUBLANG_UZBEK_LATIN' : 0x01, + 'SUBLANG_UZBEK_CYRILLIC' : 0x02, + 'SUBLANG_VIETNAMESE_VIETNAM' : 0x01, + 'SUBLANG_WELSH_UNITED_KINGDOM' : 0x01, + 'SUBLANG_WOLOF_SENEGAL' : 0x01, + 'SUBLANG_XHOSA_SOUTH_AFRICA' : 0x01, + 'SUBLANG_YAKUT_RUSSIA' : 0x01, + 'SUBLANG_YI_PRC' : 0x01, + 'SUBLANG_YORUBA_NIGERIA' : 0x01, + 'SUBLANG_ZULU_SOUTH_AFRICA' : 0x01, +} + + +''' +This dictionary defines the language lookup table. The key is the language ISO +country code, and the value specifies the corresponding code page, primary +language and sublanguage. + +LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx +Codepage resource: http://www.science.co.il/language/locale-codes.asp +Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx + +There is no appropriate sublang for Spanish (Latin America) [es-419], so we +use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other +Latin American countries, Mexican Spanish is supported by VERSIONINFO: +http://msdn.microsoft.com/en-us/library/aa381058.aspx + +''' +_LANGUAGE_MAP = { + # Language neutral LCID, unicode(1200) code page. + 'neutral' : [ 1200, 'LANG_NEUTRAL', 'SUBLANG_NEUTRAL' ], + # LANG_USER_DEFAULT LCID, unicode(1200) code page. + 'userdefault' : [ 1200, 'LANG_NEUTRAL', 'SUBLANG_DEFAULT' ], + 'fake-bidi' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], + 'af' : [ 1252, 'LANG_AFRIKAANS', 'SUBLANG_DEFAULT' ], + 'am' : [ 1200, 'LANG_AMHARIC', 'SUBLANG_DEFAULT' ], + 'ar' : [ 1256, 'LANG_ARABIC', 'SUBLANG_DEFAULT' ], + 'bg' : [ 1251, 'LANG_BULGARIAN', 'SUBLANG_DEFAULT' ], + 'bn' : [ 1200, 'LANG_BENGALI', 'SUBLANG_DEFAULT' ], + 'ca' : [ 1252, 'LANG_CATALAN', 'SUBLANG_DEFAULT' ], + 'cs' : [ 1250, 'LANG_CZECH', 'SUBLANG_DEFAULT' ], + 'da' : [ 1252, 'LANG_DANISH', 'SUBLANG_DEFAULT' ], + 'de' : [ 1252, 'LANG_GERMAN', 'SUBLANG_GERMAN' ], + 'el' : [ 1253, 'LANG_GREEK', 'SUBLANG_DEFAULT' ], + 'en' : [ 1200, 'LANG_ENGLISH', 'SUBLANG_ENGLISH_US' ], + 'en-GB' : [ 1038, 'LANG_ENGLISH', 'SUBLANG_ENGLISH_UK' ], + 'es' : [ 1252, 'LANG_SPANISH', 'SUBLANG_SPANISH_MODERN' ], + # LCID for Mexico; Windows does not support L.A. LCID. + 'es-419' : [ 1252, 'LANG_SPANISH', 'SUBLANG_SPANISH_MEXICAN' ], + 'et' : [ 1257, 'LANG_ESTONIAN', 'SUBLANG_DEFAULT' ], + 'eu' : [ 1252, 'LANG_BASQUE', 'SUBLANG_DEFAULT' ], + 'fa' : [ 1256, 'LANG_PERSIAN', 'SUBLANG_DEFAULT' ], + 'fi' : [ 1252, 'LANG_FINNISH', 'SUBLANG_DEFAULT' ], + 'fil' : [ 1252, 'LANG_FILIPINO', 'SUBLANG_DEFAULT' ], + 'fr' : [ 1252, 'LANG_FRENCH', 'SUBLANG_FRENCH' ], + 'fr-CA' : [ 1252, 'LANG_FRENCH', 'SUBLANG_FRENCH_CANADIAN' ], + 'gl' : [ 1252, 'LANG_GALICIAN', 'SUBLANG_DEFAULT' ], + 'gu' : [ 1200, 'LANG_GUJARATI', 'SUBLANG_DEFAULT' ], + 'he' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], + 'hi' : [ 1200, 'LANG_HINDI', 'SUBLANG_DEFAULT' ], + 'hr' : [ 1252, 'LANG_CROATIAN', 'SUBLANG_DEFAULT' ], + 'hu' : [ 1250, 'LANG_HUNGARIAN', 'SUBLANG_DEFAULT' ], + 'id' : [ 1252, 'LANG_INDONESIAN', 'SUBLANG_DEFAULT' ], + 'is' : [ 1252, 'LANG_ICELANDIC', 'SUBLANG_DEFAULT' ], + 'it' : [ 1252, 'LANG_ITALIAN', 'SUBLANG_DEFAULT' ], + 'iw' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], + 'ja' : [ 932, 'LANG_JAPANESE', 'SUBLANG_DEFAULT' ], + 'kn' : [ 1200, 'LANG_KANNADA', 'SUBLANG_DEFAULT' ], + 'ko' : [ 949, 'LANG_KOREAN', 'SUBLANG_KOREAN' ], + 'lt' : [ 1257, 'LANG_LITHUANIAN', 'SUBLANG_LITHUANIAN' ], + 'lv' : [ 1257, 'LANG_LATVIAN', 'SUBLANG_DEFAULT' ], + 'ml' : [ 1200, 'LANG_MALAYALAM', 'SUBLANG_DEFAULT' ], + 'mr' : [ 1200, 'LANG_MARATHI', 'SUBLANG_DEFAULT' ], + # Malay (Malaysia) [ms-MY] + 'ms' : [ 1252, 'LANG_MALAY', 'SUBLANG_DEFAULT' ], + 'nb' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_NORWEGIAN_BOKMAL' ], + 'ne' : [ 1200, 'LANG_NEPALI', 'SUBLANG_NEPALI_NEPAL' ], + 'nl' : [ 1252, 'LANG_DUTCH', 'SUBLANG_DEFAULT' ], + 'nn' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_NORWEGIAN_NYNORSK' ], + 'no' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_DEFAULT' ], + 'or' : [ 1200, 'LANG_ORIYA', 'SUBLANG_DEFAULT' ], + 'pa' : [ 1200, 'LANG_PUNJABI', 'SUBLANG_PUNJABI_INDIA' ], + 'pl' : [ 1250, 'LANG_POLISH', 'SUBLANG_DEFAULT' ], + 'pt-BR' : [ 1252, 'LANG_PORTUGUESE', 'SUBLANG_DEFAULT' ], + 'pt-PT' : [ 1252, 'LANG_PORTUGUESE', 'SUBLANG_PORTUGUESE' ], + 'ro' : [ 1250, 'LANG_ROMANIAN', 'SUBLANG_DEFAULT' ], + 'ru' : [ 1251, 'LANG_RUSSIAN', 'SUBLANG_DEFAULT' ], + 'sa' : [ 1200, 'LANG_SANSKRIT', 'SUBLANG_SANSKRIT_INDIA' ], + 'si' : [ 1200, 'LANG_SINHALESE', 'SUBLANG_SINHALESE_SRI_LANKA' ], + 'sk' : [ 1250, 'LANG_SLOVAK', 'SUBLANG_DEFAULT' ], + 'sl' : [ 1250, 'LANG_SLOVENIAN', 'SUBLANG_DEFAULT' ], + 'sr' : [ 1250, 'LANG_SERBIAN', 'SUBLANG_SERBIAN_LATIN' ], + 'sv' : [ 1252, 'LANG_SWEDISH', 'SUBLANG_SWEDISH' ], + 'sw' : [ 1252, 'LANG_SWAHILI', 'SUBLANG_DEFAULT' ], + 'ta' : [ 1200, 'LANG_TAMIL', 'SUBLANG_DEFAULT' ], + 'te' : [ 1200, 'LANG_TELUGU', 'SUBLANG_DEFAULT' ], + 'th' : [ 874, 'LANG_THAI', 'SUBLANG_DEFAULT' ], + 'ti' : [ 1200, 'LANG_TIGRIGNA', 'SUBLANG_TIGRIGNA_ERITREA' ], + 'tr' : [ 1254, 'LANG_TURKISH', 'SUBLANG_DEFAULT' ], + 'uk' : [ 1251, 'LANG_UKRAINIAN', 'SUBLANG_DEFAULT' ], + 'ur' : [ 1200, 'LANG_URDU', 'SUBLANG_DEFAULT' ], + 'vi' : [ 1258, 'LANG_VIETNAMESE', 'SUBLANG_DEFAULT' ], + 'zh-CN' : [ 936, 'LANG_CHINESE', 'SUBLANG_CHINESE_SIMPLIFIED' ], + 'zh-HK' : [ 950, 'LANG_CHINESE', 'SUBLANG_CHINESE_HONGKONG' ], + 'zh-TW' : [ 950, 'LANG_CHINESE', 'SUBLANG_CHINESE_TRADITIONAL' ], + 'zu' : [ 1200, 'LANG_ZULU', 'SUBLANG_DEFAULT' ], +} + + +# Right-To-Left languages +_RTL_LANGUAGES = ( + 'ar', # Arabic + 'fa', # Farsi + 'iw', # Hebrew + 'ks', # Kashmiri + 'ku', # Kurdish + 'ps', # Pashto + 'ur', # Urdu + 'yi', # Yiddish +) + + +def GetCodepage(language): + """ Returns the codepage for the given |language|. """ + lang = _LANGUAGE_MAP[language] + return "%04x" % lang[0] + + +def GetCodepageDecimal(language): + """ Returns the codepage for the given |language| as a decimal value. """ + lang = _LANGUAGE_MAP[language] + return "%d" % lang[0] + + +def GetLangId(language): + """ Returns the language id for the given |language|. """ + lang = _LANGUAGE_MAP[language] + return "%04x" % (_LANGUAGE_PRIMARY[lang[1]] | (_LANGUAGE_SUB[lang[2]] << 10)) + + +def GetPrimaryLanguage(language): + """ Returns the primary language ID for the given |language|. """ + lang = _LANGUAGE_MAP[language] + return _LANGUAGE_PRIMARY[lang[1]] + + +def GetSublanguage(language): + """ Returns the sublanguage ID for the given |language|. """ + lang = _LANGUAGE_MAP[language] + return _LANGUAGE_SUB[lang[2]] + + +def IsRtlLanguage(language): + return language in _RTL_LANGUAGES; + + +def NormalizeLanguageCode(language): + return language.replace('_', '-', 1) + + +def ReadValuesFromFile(values_dict, file_name): + """ + Reads KEYWORD=VALUE settings from the specified file. + + Everything to the left of the first '=' is the keyword, + everything to the right is the value. No stripping of + white space, so beware. + + The file must exist, otherwise you get the Python exception from open(). + """ + for line in open(file_name, 'r').readlines(): + key, val = line.rstrip('\r\n').split('=', 1) + values_dict[key] = val + + +def ReadMessagesFromFile(file_name): + """ + Reads messages from a 'chrome_messages_json' file. + + The file must exist, otherwise you get the Python exception from open(). + """ + messages_file = io.open(file_name, encoding='utf-8-sig') + messages = json.load(messages_file) + messages_file.close() + + values = {} + for key in messages.keys(): + values[key] = unicode(messages[key]['message']); + return values + + +def WriteIfChanged(file_name, contents, encoding='utf-16'): + """ + Writes the specified contents to the specified file_name + iff the contents are different than the current contents. + """ + try: + target = io.open(file_name, 'r') + old_contents = target.read() + except EnvironmentError: + pass + except UnicodeDecodeError: + target.close() + os.unlink(file_name) + else: + if contents == old_contents: + return + target.close() + os.unlink(file_name) + io.open(file_name, 'w', encoding=encoding).write(contents) + + +class MessageMap: + """ Provides a dictionary of localized messages for each language.""" + def __init__(self, languages, messages_path): + self.language = None + self.message_map = {} + + # Populate the message map + if messages_path: + for language in languages: + file_name = os.path.join(messages_path, + language.replace('-', '_', 1), + 'messages.json') + self.message_map[language] = ReadMessagesFromFile(file_name) + + def GetText(self, message): + """ Returns a localized message for the current language. """ + return self.message_map[self.language][message] + + def SelectLanguage(self, language): + """ Selects the language to be used when retrieving localized messages. """ + self.language = language + + def MakeSelectLanguage(self): + """ Returns a function that can be used to select the current language. """ + return lambda language: self.SelectLanguage(language) + + def MakeGetText(self): + """ Returns a function that can be used to retrieve a localized message. """ + return lambda message: self.GetText(message) + + +def Localize(source, target, options): + # Load jinja2 library. + if options.jinja2: + jinja2_path = os.path.normpath(options.jinja2) + else: + jinja2_path = os.path.normpath(os.path.join(os.path.abspath(__file__), + '../../../third_party/jinja2')) + sys.path.append(os.path.split(jinja2_path)[0]) + from jinja2 import Environment, FileSystemLoader + + # Create jinja2 environment. + (template_path, template_name) = os.path.split(source) + env = Environment(loader=FileSystemLoader(template_path), + extensions=['jinja2.ext.do', 'jinja2.ext.i18n']) + + # Register custom filters. + env.filters['GetCodepage'] = GetCodepage + env.filters['GetCodepageDecimal'] = GetCodepageDecimal + env.filters['GetLangId'] = GetLangId + env.filters['GetPrimaryLanguage'] = GetPrimaryLanguage + env.filters['GetSublanguage'] = GetSublanguage + + # Set the list of languages to use + languages = map(NormalizeLanguageCode, options.languages) + context = { 'languages' : languages } + env.globals['IsRtlLanguage'] = IsRtlLanguage + + # Load the localized messages and register the message map with jinja2.i18n + # extension. + message_map = MessageMap(languages, options.messages_path) + env.globals['SelectLanguage'] = message_map.MakeSelectLanguage() + env.install_gettext_callables(message_map.MakeGetText(), + message_map.MakeGetText()); + + # Add OFFICIAL_BUILD variable the same way chrome/tools/build/version.py + # does. + if os.environ.get('CHROME_BUILD_TYPE') == '_official': + context['official_build'] = '1' + else: + context['official_build'] = '0' + + # Add all variables defined in the command line. + if options.define: + for define in options.define: + context.update(dict([define.split('=', 1)])); + + # Read KEYWORD=VALUE variables from file. + if options.input: + for file_name in options.input: + ReadValuesFromFile(context, file_name) + + template = env.get_template(template_name) + WriteIfChanged(target, template.render(context), options.encoding); + return 0; + + +def main(): + usage = "Usage: localize [options] <input> <output>" + parser = OptionParser(usage=usage) + parser.add_option( + '-d', '--define', dest='define', action='append', type='string', + help='define a variable (VAR=VALUE).') + parser.add_option( + '-i', '--input', dest='input', action='append', type='string', + help='read variables from INPUT.') + parser.add_option( + '-l', '--language', dest='languages', action='append', type='string', + help='add LANGUAGE to the list of languages to use.') + parser.add_option( + '--encoding', dest='encoding', type='string', default='utf-16', + help="set the encoding of <output>. 'utf-16' is the default.") + parser.add_option( + '--jinja2', dest='jinja2', type='string', + help="specifies path to the jinja2 library.") + parser.add_option( + '--messages_path', dest='messages_path', type='string', + help="set path to localized messages.") + + options, args = parser.parse_args() + if len(args) != 2: + parser.error('Two positional arguments (<input> and <output>) are expected') + if not options.languages: + parser.error('At least one language must be specified') + if not options.messages_path: + parser.error('--messages_path is required') + + return Localize(args[0], args[1], options) + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/remoting/tools/verify_resources.py b/remoting/tools/verify_resources.py index 045f95d..4ffd494 100755 --- a/remoting/tools/verify_resources.py +++ b/remoting/tools/verify_resources.py @@ -72,6 +72,10 @@ def ExtractTagFromLine(file_type, line): # Manifest style m = re.search('__MSG_(.*)__', line) if m: return m.group(1) + elif file_type == 'jinja2': + # Jinja2 template file + m = re.search('\{\%\s+trans\s+\%\}([A-Z0-9_]+)\{\%\s+endtrans\s+\%\}', line) + if m: return m.group(1) return None @@ -85,7 +89,7 @@ def VerifyFile(filename, messages, used_tags): base_name, extension = os.path.splitext(filename) extension = extension[1:] - if extension not in ['js', 'cc', 'html', 'json']: + if extension not in ['js', 'cc', 'html', 'json', 'jinja2']: raise Exception("Unknown file type: %s" % extension) result = True diff --git a/remoting/version.rc.version b/remoting/version.rc.version deleted file mode 100644 index f45f326..0000000 --- a/remoting/version.rc.version +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <verrsrc.h> - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -// Let .VER file to select the binary that is being compiled. -#define BINARY_HOST_PLUGIN 1 -#define BINARY_HOST_ME2ME 2 -#define BINARY_DESKTOP 3 -#define BINARY_CORE 4 -#define BINARY @BINARY@ - -#if (BINARY == BINARY_HOST_PLUGIN) -#define FILE_DESCRIPTION "@HOST_PLUGIN_DESCRIPTION@" -#elif (BINARY == BINARY_HOST_ME2ME) -#define FILE_DESCRIPTION "@HOST_ME2ME_DESCRIPTION@" -#elif (BINARY == BINARY_DESKTOP) -#define FILE_DESCRIPTION "@DESKTOP_DESCRIPTION@" -#elif (BINARY == BINARY_CORE) -#define FILE_DESCRIPTION "@CORE_DESCRIPTION@" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @MAJOR@,@REMOTING_PATCH@,@BUILD@,@PATCH@ - PRODUCTVERSION @MAJOR@,@REMOTING_PATCH@,@BUILD@,@PATCH@ - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE @FILE_TYPE@ - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "@COMPANY_FULLNAME@" - VALUE "FileDescription", FILE_DESCRIPTION - VALUE "FileVersion", "@MAJOR@.@REMOTING_PATCH@.@BUILD@.@PATCH@" - VALUE "InternalName", "@INTERNAL_NAME@" - VALUE "LegalCopyright", "@COPYRIGHT@" - VALUE "OriginalFilename", "@ORIGINAL_FILENAME@" - VALUE "ProductName", "@PRODUCT_FULLNAME@" - VALUE "ProductVersion", "@MAJOR@.@REMOTING_PATCH@.@BUILD@.@PATCH@" - VALUE "LastChange", "@LASTCHANGE@" - VALUE "Official Build", "@OFFICIAL_BUILD@" -#if (BINARY == BINARY_HOST_PLUGIN) - VALUE "MIMEType", "@HOST_PLUGIN_MIME_TYPE@" -#endif - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END |