尝试制作多语言安装程序 - 该过程通常正在运行,但似乎无法安装要安装的本地化文件。
每个本地化安装程序都可以作为独立安装程序正常工作,并安装本地化文件,如eula.pdf。
我希望我只是在变换生成步骤中错过了一个标志(或者可能使用了错误的工具?)
通过为每种语言安装一堆安装程序来开始处理。
要构建每个安装程序,我们使用-b "folder"
和-loc "folder"
选项“点亮”以指定包含一些备用文件内容的每种语言,例如licence.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差异。使用Window SDK中的Windows\v7.1\Bin\MsiTran.exe
MST对于内容的变化似乎有点小。
使用Windows\v7.1\Samples\sysmgmt\msi\scripts\wisubstg.vbs
使用非英语语言安装显示整个安装程序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-US\my.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
其他语言的具体内容,例如1036
for fr-FR
答案 0 :(得分:2)
好的,经过几天的搜索,我找到了一篇描述这个问题的文章。 How To Localize the Setup GUI and Deliver Localized Files Using a MST
问题是MST没有包含&#39; _Streams&#39;表元素,这是存储CAB文件的地方。
你可以通过几种方式 -
1)制作多个文件&amp;基于语言或文化的条件包含的不同语言的组件条目
这意味着如果您想更改支持的语言,请更改您的wx。
<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***'>
<Condition><![CDATA[(ProductLanguage = "1033")]]></Condition>
<File Id='License.pdf' Name='!(loc.EULA)' Source='en-US\License(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-BR\License(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
根据How To Localize the Setup GUI and Deliver Localized Files Using a MST。
3)自动将本地化项目拆分为具有本地化名称的单独CAB
然后重新编译和管理CAB文件的额外过程,而不是重新编译。
额外流程 -
*提取CAB文件以及生成mst,
*然后在合并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
我选择了3 我希望其他人觉得这很有用。 注意:的
并且ant build看起来像下面这样。
<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.5\bin"/>
<property name="binarieslocation" value="build"/>
<property name="msiwixsource" value="install"/>
<property name="msiwixobjects" value="${msiwixsource}\obj\x64\Release"/>
<!-- <dirname property="windowsSDK" file="C:\Program Files\Microsoft SDKs\Windows\v7.1\"/> Ant doesn't like path segments with . -->
<property name="windowsSDKBin" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\MsiTran.exe"/>
<property name="windowsSDKCab" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\MsiDb.Exe"/>
<property name="windowsSDKMsiStorage" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiSubStg.vbs"/>
<property name="windowsSDKMsiStream" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiStream.vbs"/>
<property name="windowsSDKMsiLanguages" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiLangId.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-US\my.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-US\my.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>