wix工具集:如何使用针对多种语言本地化的产品名称创建单个exe

时间:2015-03-25 21:30:17

标签: localization wix installer bootstrapper wix3.9

我正在使用WiX v3.9 R2来创建我的安装程序。我将安装程序本地化为多种语言,效果很好。但是,它始终使用程序和程序中的应用程序的英文名称。功能,无论格式和显示语言设置为何种语言。

如何告诉它在我的应用程序中使用本地化名称,在“程序”和“程序”中。特征

修改

澄清一下:我认为我需要的是一种在安装时根据用户的语言更改Bundle名称属性(或[WixBundleName])的方法。这可能吗?

或者失败了,人们目前如何使用WiX Bundle,最终将程序名称本地化为程序和功能?

编辑2: 来自WiX site

  

WixBundleName - 获取包的名称(来自Bundle / @ Name)。这个   变量也可以由bootstrapper应用程序设置来修改   在运行时捆绑名称。

所以听起来这可以做到 - 但是怎么做?

编辑3: 这是我目前的Bundle,供参考。链中的最后一项是我的申请。

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
    <Bundle Name="Map Creator"
            Version="$(var.ProductVersion)" 
            Manufacturer="FMOsoft" 
            IconSourceFile="$(var.KarteDir)\assets\logo\ico\icon.ico" 
            UpgradeCode="[GUID]" 
            AboutUrl="http://fmosoft.com/MapCreator"
            Copyright="Copyright© 2015, FMOsoft">

        <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkSidebarLicense">
          <bal:WixStandardBootstrapperApplication
            LocalizationFile="$(var.KarteDir)\install\win\L10n\installer\thm_en_us.wxl"
            ThemeFile="$(var.KarteDir)\install\win\HyperlinkSidebarTheme_fmosoft.xml"
            LogoFile="$(var.KarteDir)\assets\logo\bmp\logo_64.bmp"
            LogoSideFile="logoside.bmp"
            ShowVersion="yes"
            LicenseFile="$(var.KarteDir)\install\license_en.html"
            SuppressOptionsUI="yes"
            LaunchTarget="[ProgramFiles6432Folder]\FMOsoft\MapCreator\MapCreator.exe"
            />

          <!-- WixStdBa requires specific names, at run time, in the temporary .BA1 folder.  XML and png file is only needed for layout changes. 
               Payload/@Name for .wxl must be <lcid>\thm.wxl 
               Payload/@Name for .xml must be <lcid>\thm.xml AND must also have logo.png in same folder.--> 
          <Payload Id="theme_en_us" Compressed="yes"  Name="1033\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_en_us.wxl"/> 
          <Payload Id="license_en_us" Compressed="yes"  Name="1033\license.html" SourceFile="$(var.KarteDir)\install\license_en.html"/> 
          <Payload Id="theme_es_es" Compressed="yes"  Name="1034\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_es_es.wxl"/> 
          <Payload Id="license_es_es" Compressed="yes"  Name="1034\license.html" SourceFile="$(var.KarteDir)\install\license_es.html"/> 
          <Payload Id="theme_fr_fr_xml" Compressed="yes"  Name="1036\thm.xml" SourceFile="$(var.KarteDir)\install\win\L10n\installer\HyperlinkSidebarTheme_fmosoft_fr.xml"/> 
          <Payload Id="theme_fr_fr" Compressed="yes"  Name="1036\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_fr_fr.wxl"/> 
          <Payload Id="theme_fr_fr_logo" Compressed="yes"  Name="1036\logo.png" SourceFile="$(var.KarteDir)\assets\logo\bmp\logo_64.bmp"/> 
          <Payload Id="theme_fr_fr_sidelogo" Compressed="yes"  Name="1036\logoside.png" SourceFile="$(var.KarteDir)\install\win\logoside.bmp"/> 
          <Payload Id="license_fr_fr" Compressed="yes"  Name="1036\license.html" SourceFile="$(var.KarteDir)\install\license_fr.html"/> 
          <Payload Id="theme_pt_br" Compressed="yes"  Name="1046\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_pt_br.wxl"/>
          <Payload Id="license_pt_br" Compressed="yes"  Name="1046\license.html" SourceFile="$(var.KarteDir)\install\license_pt.html"/> 
          <Payload Id="theme_id" Compressed="yes"  Name="1057\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_id.wxl"/>
          <Payload Id="license_id" Compressed="yes"  Name="1057\license.html" SourceFile="$(var.KarteDir)\install\license_id.html"/> 
        </BootstrapperApplicationRef>

        <WixVariable Id="WixStdbaLicenseUrl" Value="license.html" />
        <Variable Name="MyProductVersion" Value="$(var.ProductVersion)" />
        <!-- There must be a better way to show the localized name of the app in the setup, but this works. -->
        <Variable Name="AppName_es" Value="Creador de Mapas"/>
        <Variable Name="AppName_fr" Value="Créateur de Carte"/>
        <Variable Name="AppName_pt" Value="Criador de Mapas"/>
        <Variable Name="AppName_id" Value="Pencipta Peta"/>

        <Chain>
            <ExePackage SourceFile="vcredist_x64.exe" PerMachine="yes" Permanent="yes" Vital="yes" Compressed="yes" InstallCommand="/quiet /norestart" InstallCondition="VersionNT64"/>
            <ExePackage SourceFile="vcredist_x86.exe" PerMachine="yes" Permanent="yes" Vital="yes" Compressed="yes" InstallCommand="/quiet /norestart" InstallCondition="NOT VersionNT64"/>
            <PackageGroupRef Id="OldMapEditorPackage"/>
            <MsiPackage Vital="yes" SourceFile="$(var.BuildDir)out\map-creator-$(var.Platform).msi" />
        </Chain>
    </Bundle>
</Wix>

2 个答案:

答案 0 :(得分:1)

有一个开放的功能请求:http://wixtoolset.org/issues/4045/。此解决方案将允许您提供程序&amp;功能将查询显示名称,因此如果用户更改操作系统语言,它将会更改。

在有人实现该功能之前,您可以通过设置WixBundleName变量来完成此操作。如果您正在编写自定义BA,请拨打IBootstrapperEngine::SetVariableString

如果你正在使用WixStdBA,你将不得不使用没有很好记录的BAFunctions dll来调用这个方法。有一个示例项目here。请注意,最近添加的WixStdBALanguageId variable可以帮助您了解当前的语言。

要添加BAFunctions.dll,只需将其添加为有效负载:

<BootstrapperApplicationRef ...>
  <Payload Name="BAFunctions.dll" SourceFile="path\to\your.dll" />
</BootstrapperApplicationRef>

答案 1 :(得分:0)

如果它有用,因为我花了很长时间才弄明白,这是我如何本地化WixBundleName所以它本地化在程序&amp;特征。这是基于肖恩·霍尔的答案和评论。

这适用于WiX 3.10.0.1519 weekly build, built on Thursday, Mar. 19 2015

/* This document describes how we build bafunctions.dll.

1. Install the version of WiX you want to use.  This is necessary because it sets some environment variables or something, 
    and provides some .h files needed to get the BAFunctions project to compile.
2. Download the wixXX-debug.zip file from the same page where the WiX installer is for the version of WiX you want.
3. Unzip and browse to [wixXX-debug\src\burn\Samples\bafunctions\ and open the project in Visual Studio 2010.
4. In WixBootstrapperBAFunction.cpp, add our code as shown below.
5. Rebuild solution in Release configuration.
6. copy bafunctions\release\bafunctions.dll to Map Creator build machine, [map_creator]\install\win\[Wix_X.X]

*/

// In WixBootstrapperBAFunction.cpp:

// comment out this line (line 32 in WiX 3.10):

    STDMETHODIMP OnDetectComplete() { return S_OK; }

/* uncomment the commented-out OnDetectComplete procedure, and in the section marked
// YOUR CODE GOES HERE
add this code:
*/
        LONGLONG lang_id = NULL;
        LPWSTR bundle_name = NULL;
        LPWSTR platform = NULL;
        LPWSTR orig_name = NULL;

        // get the language the user is using
        BalGetNumericVariable(L"WixStdBALanguageId", &lang_id);
        BalExitOnFailure(hr, "Failed to get variable 'WixStdBALanguageId'.");

        // log the language id
        char msg[66];   // 66 I'm sure is big enough
        sprintf_s(msg, 67, "%s%d", "WixStdBALanguageId is ", lang_id);
        BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg);

        /* I don't know how to pass custom variables from the .wxs, so I tried below to use the built-in HelpTelephone.
            That doesn't work either - apparently we can only get variables listed in:
            http://wixtoolset.org/documentation/manual/v3/bundle/bundle_built_in_variables.html
        BalGetStringVariable(L"WixBundleHelpTelephone", &platform);
        BalExitOnFailure(hr, "Failed to get WixBundleHelpTelephone variable.");*/

        // Since I don't know how to pass a custom variable from the .wxs, I get the @Name attribute of the Bundle (from the .wxs),
        //  and I parse out the platform.
        BalGetStringVariable(L"WixBundleName", &orig_name);
        BalExitOnFailure(hr, "Failed to get WixBundleName variable.");

        platform = wcsrchr(orig_name, '(');

        // log the platform.
        char msg5[66];  // 66 I'm sure is big enough
        sprintf_s(msg5, 67, "%s%s", "platform is ", platform);
        BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg5);

        // Select the localized bundle name
        // I got the language codes from https://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
        switch (lang_id) {
            case 1036:
            case 2060:
            case 3084:
            case 4108:
            case 5132:
            case 6156:
            case 7180:
            case 8204:
            case 9228:
            case 10252:
            case 11276:
            case 12300:
            case 13324:
            case 14348:
            case 15372:
            case 58380:
                // French
                bundle_name = L"Créateur de Carte";
                break;

            case 1057:
                // Indonesian
                bundle_name = L"Pencipta Peta";
                break;

            case 1046:
            case 2070:
                // Portuguese
                bundle_name = L"Criador de Mapas";
                break;

            case 1034:
            case 2058:
            case 3082:
            case 4106:
            case 5130:
            case 6154:
            case 7178:
            case 8202:
            case 9226:
            case 10250:
            case 11274:
            case 12298:
            case 13322:
            case 14346:
            case 15370:
            case 16394:
            case 17418:
            case 18442:
            case 19466:
            case 20490:
            case 21514:
            case 22538:
                // Spanish
                bundle_name = L"Creador de Mapas";
                break;

            default:
                bundle_name = L"Map Creator";
        }

        // log the new bundle name.
        char msg2[66];  // 66 I'm sure is big enough
        sprintf_s(msg2, 67, "%s%s", "bundle_name is ", bundle_name);
        BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg2);

        // append the platform to the end of the bundle name
        wchar_t bundle_name_platform[80];
        wcscpy_s(bundle_name_platform, bundle_name);
        wcscat_s(bundle_name_platform, L" ");
        wcscat_s(bundle_name_platform, platform);

        // log the final bundle name (which includes the platform)
        char msg3[66];  // 66 I'm sure is big enough
        sprintf_s(msg3, 67, "%s%s", "bundle_name_platform is ", bundle_name_platform);
        BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg3);

        // set the name of our bundle
        hr = m_pEngine->SetVariableString(L"WixBundleName", bundle_name_platform);
        BalExitOnFailure(hr, "Failed to set WixBundleName variable.");