尝试制作一个多语言安装程序-该过程一般正常,但对于要安装的本地化文件似乎失败。
每个本地化的安装程序都可以独立运行,并安装像eula.pdf这样的本地化文件。
我希望我只是错过了转换生成步骤的标志(或者可能使用错误的工具?)
每一种语言都有一堆安装程序。
为了构建每个安装程序,我们使用-b "folder"
和-loc "folder"
选项来指定每种语言,其中包括一些替代文件内容,如license .pdf。
要本地化的文件有一个通用的源名称
<File Id='License.pdf' Name='eula.pdf' Source='License(EULA).pdf' KeyPath='yes'/>
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
文件夹,例如
en-US/License(EULA).pdf
en-US/License.rtf
en-US/Product.wxl
fr-FR/License(EULA).pdf
fr-FR/License.rtf
fr-FR/Product.wxl
还有一些文件,如binary.dll和binary.exe,它们没有本地化,并且对所有msi都是相同的-不要期望在MST中看到它们。
该过程的下一步是在基本语言(英语)和其他每种语言之间创建MST差异。使用Windowsv7.1BinMsiTran.exe
从windows SDK
对于内容的变化,MST似乎有点小。
使用Windowsv7.1Samplessysmgmtmsiscriptswisubstg.vbs
将所有MST文件合并到单个安装程序中
以非英语的语言安装会显示整个安装程序UI,包括本地化的rtf版本的许可证,但磁盘上的eula.pdf始终是基础英语。
使用Ant-dotnet任务来运行构建(以防它产生差异)msi构建任务
<wix mode="light" target="${outlocation}${lang.folder}my.msi" wixHome="${wixhome}">
<lightArg line="-b "${location}""/> <!-- provide the location of the signable binaries -->
<lightArg line="-b "${msiwixsource}Localisation${lang.folder}""/> <!-- provide the location of the localisation -->
<lightArg line="-sice:ICE57"/>
<lightArg line="-cultures:${lang.culture}"/>
<lightArg line="-loc "${msiwixsource}Localisation${lang.folder}Product.wxl""/>
<lightArg line="-ext "${wixhome}WixUtilExtension.dll""/>
<lightArg line="-ext "${wixhome}WixUIExtension.dll""/>
<lightArg line="-ext "${wixhome}WixFirewallExtension.dll""/>
<lightArg line="-ext "${wixhome}WixNetFxExtension.dll""/>
<sources dir="${msiwixobjects}">
<include name="*.wixobj"/>
</sources>
<moresources dir="${msiwixsource}Localisation${lang.folder}">
<include name="*"/>
</moresources>
<moresources dir="${location}">
<include name="binary.dll,binary.exe"/>
</moresources>
</wix>
转换任务
<exec executable="${windowsSDKBin}">
<arg value="-g"/>
<arg value="${outlocation}en-USmy.msi"/>
<arg value="${outlocation}${lang.folder}my.msi"/>
<arg value="${outlocation}${lang.folder}my.mst"/>
</exec>
重新打包任务
<exec executable="cscript">
<arg value="${windowsSDKMsi}"/>
<arg value="${outlocation}my.msi"/>
<arg value="${outlocation}${lang.folder}my.mst"/>
<arg value="${lang.id}"/>
</exec>
Product/@Language="!(loc.Lang)"在Product.wxl中指定对于英语基础,我们列出了所有其他语言的1033,1028,1029,1031,1036,1040,1041,1043,1045,1046,2052,3082
,例如fr-FR的1036
好,经过几天的搜索,我找到了一篇描述这个问题的文章。如何使用MST本地化安装GUI和交付本地化文件。
问题是MST不包括'_Streams'表元素,这是存储CAB文件的地方。
你可以有多种选择-
1)制作多个文件&基于语言或文化条件包含的不同语言的组件条目
这意味着如果您想更改所支持的语言,请更改wxs。
<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***'>
<Condition><![CDATA[(ProductLanguage = "1033")]]></Condition>
<File Id='License.pdf' Name='!(loc.EULA)' Source='en-USLicense(EULA).pdf' KeyPath='yes'/>
</Component>
<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***'>
<Condition><![CDATA[(ProductLanguage = "1046")]]></Condition>
<File Id='License.pdf' Name='!(loc.EULA)' Source='pt-BRLicense(EULA).pdf' KeyPath='yes'/>
</Component>
... add a new block each time you add a language, changes to files have to be duplicated for every block.
这意味着重新编译而不仅仅是重新链接wxl。您仍然需要重新打包mst文件。
2)手动调整本地化的MSI
根据如何本地化安装GUI和使用MST交付本地化文件。
3)自动将本地化项目拆分为具有本地化名称的单独CAB
不是重新编译,而是重新链接和管理CAB文件的额外过程。额外的进程-*在生成mst的同时提取CAB文件,
*然后合并MST时也添加cab文件。
添加一个具有本地化名称的额外媒体-我使用lang id,因为它很方便
<Media Id="2" Cabinet="localised_!(loc.LANG).cab" EmbedCab="yes" />
将本地化的文件/组件更改为来自新媒体
<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***' DiskId='2'>
<File Id='License.pdf' Name='!(loc.EULA)' Source='License(EULA).pdf' KeyPath='yes'/>
</Component>
当使用MSITran.exe
生成转换时,也使用MsiDb.Exe
导出本地化的CAB文件当使用WiSubStg.vbs
将转换合并到基本MSI时,还使用WiStram.vbs
将CAB文件添加到_Streams
我选择了选项3我希望其他人觉得这有用。注意:
- 我没有写很多ANT,所以请随时提供建议
- 我们构建了一个用于测试的无符号版本和用于发布的有符号版本,因此需要调整输入/输出位置以找到二进制文件和msi。
和ant构建看起来像下面这样。
<taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="buildjars"/>
<taskdef name="for" classname="net.sf.antcontrib.logic.ForTask" classpathref="buildjars"/>
<taskdef name="wix" classname="org.apache.ant.dotnet.wix.WixTask" classpathref="buildjars"/>
<property name="wixhome" value="C:Program Files (x86)Windows Installer XML v3.5bin"/>
<property name="binarieslocation" value="build"/>
<property name="msiwixsource" value="install"/>
<property name="msiwixobjects" value="${msiwixsource}objx64Release"/>
<!-- <dirname property="windowsSDK" file="C:Program FilesMicrosoft SDKsWindowsv7.1"/> Ant doesn't like path segments with . -->
<property name="windowsSDKBin" location="C:Program FilesMicrosoft SDKsWindowsv7.1BinMsiTran.exe"/>
<property name="windowsSDKCab" location="C:Program FilesMicrosoft SDKsWindowsv7.1BinMsiDb.Exe"/>
<property name="windowsSDKMsiStorage" location="C:Program FilesMicrosoft SDKsWindowsv7.1SamplessysmgmtmsiscriptsWiSubStg.vbs"/>
<property name="windowsSDKMsiStream" location="C:Program FilesMicrosoft SDKsWindowsv7.1SamplessysmgmtmsiscriptsWiStream.vbs"/>
<property name="windowsSDKMsiLanguages" location="C:Program FilesMicrosoft SDKsWindowsv7.1SamplessysmgmtmsiscriptsWiLangId.vbs"/>
<property name="cultureBase" value="en-US:en-US:1033"/>
<property name="cultures" value="pt-BR:pt-BR:1046,cs-CZ:en-US:1029"/>
<target name="installer">
<echo>Building ${culture} msi using binaries in "${location}"...</echo>
<propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="1"/>
<propertyregex property="lang.culture" input="${culture}" regexp="(.*):(.*):(.*)" select="2"/>
<wix mode="light" target="${outlocation}${lang.folder}my.msi" wixHome="${wixhome}">
<lightArg line="-b "${location}""/> <!-- provide the location of the signable binaries -->
<lightArg line="-b "${msiwixsource}Localisation${lang.folder}""/> <!-- provide the location of the localisation -->
<lightArg line="-sice:ICE57"/>
<lightArg line="-cultures:${lang.culture}"/>
<lightArg line="-loc "${msiwixsource}Localisation${lang.folder}Product.wxl""/>
<lightArg line="-ext "${wixhome}WixUtilExtension.dll""/>
<lightArg line="-ext "${wixhome}WixUIExtension.dll""/>
<sources dir="${msiwixobjects}">
<include name="*.wixobj"/>
</sources>
<moresources dir="${msiwixsource}Localisation${lang.folder}">
<include name="*"/>
</moresources>
<moresources dir="${location}">
<include name="binary.dll,binary.exe"/>
</moresources>
</wix>
</target>
<target name="checkTransform" depends="installer">
<uptodate property="transform.notRequired" targetfile="${outlocation}${culture}my.mst" >
<srcfiles dir= "${outlocation}en-US" includes="my.msi"/>
<srcfiles dir= "${outlocation}${lang.culture}" includes="my.msi"/>
</uptodate>
</target>
<target name="transform" depends="checkTransform" unless="transform.notRequired">
<echo>Building ${culture} mst ...</echo>
<propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="1"/>
<propertyregex property="lang.id" input="${culture}" regexp="(.*):(.*):(.*)" select="3"/>
<!-- Generate the mst 'diff' file - this does not include exporting the language specific cab file to match -->
<exec executable="${windowsSDKBin}">
<arg value="-g"/>
<arg value="${outlocation}en-USmy.msi"/>
<arg value="${outlocation}${lang.folder}my.msi"/>
<arg value="${outlocation}${lang.folder}my.mst"/>
</exec>
<!-- Exporting the language specific cab file to match -->
<delete file="localised_${lang.id}.cab" />
<delete file="${outlocation}${lang.folder}localised_${lang.id}.cab" />
<exec executable="${windowsSDKCab}">
<arg value="-d"/>
<arg value="${outlocation}${lang.folder}my.msi"/>
<arg value="-x"/>
<arg value="localised_${lang.id}.cab"/>
</exec>
<move file="localised_${lang.id}.cab" tofile="${outlocation}${lang.folder}localised_${lang.id}.cab"/>
</target>
<!-- Target to build MSIs using unsigned binaries -->
<target name="MSIs">
<!-- we always need english as it is the base multilingual -->
<antcall target="installer">
<param name="culture" value="${cultureBase}" />
<param name="location" value="${location}" />
<param name="outlocation" value="${outlocation}" />
</antcall>
<!-- build the different cultures and make transforms
parallel="true" sometimes fails-->
<for list="${cultures}" param="culture" >
<sequential>
<antcall target="transform">
<param name="culture" value="@{culture}" />
<param name="location" value="${location}" />
<param name="outlocation" value="${outlocation}" />
</antcall>
</sequential>
</for>
</target>
<!-- depends="transform" -->
<target name="transformRepack" >
<echo>Packing ${culture} mst into multilingual installer...</echo>
<propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="1"/>
<propertyregex property="lang.id" input="${culture}" regexp="(.*):(.*):(.*)" select="3"/>
<exec executable="cscript">
<arg value="${windowsSDKMsiStream}"/>
<arg value="${outlocation}my.msi"/>
<arg value="${outlocation}${lang.folder}localised_${lang.id}.cab"/>
<arg value="localised_${lang.id}.cab"/>
</exec>
<exec executable="cscript">
<arg value="${windowsSDKMsiStorage}"/>
<arg value="${outlocation}my.msi"/>
<arg value="${outlocation}${lang.folder}my.mst"/>
<arg value="${lang.id}"/>
</exec>
</target>
<target name="MSIMulti" depends="MSIs">
<echo>Making multilingual installer...</echo>
<copy file="${outlocation}en-USmy.msi" todir="${outlocation}"/>
<for list="${cultures}" param="culture">
<sequential>
<antcall target="transformRepack">
<param name="culture" value="@{culture}" />
<param name="location" value="${location}" />
<param name="outlocation" value="${outlocation}" />
</antcall>
</sequential>
</for>
<!-- report what was packed -->
<propertyregex property="lang.ids" input="${cultures}" regexp="([^:,]*):([^:]*):([^,]*)" replace="3" global="true" defaultvalue="failed"/>
<echo/>
<echo>Multilingual installer should include transform language ids </echo>
<echo>${lang.ids}</echo>
<echo>Multilingual installer reports transform language ids...</echo>
<exec executable="cscript">
<arg value="${windowsSDKMsiStorage}"/>
<arg value="${outlocation}my.msi"/>
</exec>
<exec executable="cscript">
<arg value="${windowsSDKMsiLanguages}"/>
<arg value="${outlocation}my.msi"/>
<arg value="Package"/>
<arg value="1033,${lang.ids}"/>
</exec>
</target>
<target name="UnsignedMSIMulti" >
<antcall target="MSIMulti">
<param name="location" value="${binarieslocation}" />
<param name="outlocation" value="${binarieslocation}" />
</antcall>
</target>